☰
Day 11 Linux磁盘管理与LVM实战
2026/10/15 4:01:27 网站建设 项目流程

Linux 磁盘管理与 LVM 实战:从日志轮转到启动恢复

接上一期《Linux 服务管理实战——systemd 日志与时间同步》,我们讲了日志"怎么看、怎么收"。
这一期往存储底层延伸:日志轮转(logrotate)是怎么把日志管住的、Linux 开机到底经历了什么、以及最硬核的部分——磁盘 / 分区 / LVM / 文件系统 / 挂载点这一整条链路,外加加盘、扩容、持久挂载,和一旦配错导致起不来的启动恢复。

全程命令可复制,建议边看边敲。

文章目录

  • Linux 磁盘管理与 LVM 实战:从日志轮转到启动恢复
    • 一、Logrotate 日志轮转的原理
      • 1.1 它到底怎么工作的
      • 1.2 配置文件在哪
      • 1.3 最常用的指令
      • 1.4 自己写一个轮转配置(演示)
      • 1.5 先"演习"再"真干"
    • 二、Linux 启动链(开机到底发生了什么)
      • 2.1 BIOS 与 UEFI 的区别(影响分区表)
      • 2.2 查看当前启动模式
      • 2.3 GRUB 与 systemd 常用命令
      • 2.4 拓展实战:忘记 root 密码?用救援模式进系统
    • 三、目录背后的完整映射(存储栈)
    • 四、添加磁盘后的三类证据互相验证:lsblk / blkid / findmnt
      • 4.1 三连击演示
      • 4.2 怎么"互相验证"
    • 五、磁盘分区:GPT vs MBR 与实操步骤
      • 5.1 选哪个
      • 5.2 用 parted 建 GPT 分区(推荐)
      • 5.3 查看分区结果
    • 六、格式化、临时挂载与卸载
      • 6.1 格式化(建立文件系统)
      • 6.2 临时挂载(重启失效)
      • 6.3 卸载
    • 七、持久挂载与 /etc/fstab 详解
      • 7.1 fstab 每行 6 个字段
      • 7.2 实操:把 /data 持久化
    • 八、LVM 数据卷管理:创建与扩容完整步骤
      • 8.1 概念对应
      • 8.2 场景 A:从零新建 LVM 并挂载
      • 8.3 场景 B:扩容(把磁盘"撑大")—— 重点
      • 8.4 逐步检查
    • 总结

一、Logrotate 日志轮转的原理

系统跑久了,日志会无限变大。logrotate就是专门干"日志瘦身"的定时工具——它不是守护进程,而是被cron / anacron每天定时调用一次,按规则对日志做轮转(rotate)、压缩、删除、重命名。

1.1 它到底怎么工作的

每天 (cron.daily) 触发 └── /usr/sbin/logrotate /etc/logrotate.conf ├── 读主配置 /etc/logrotate.conf ├── 逐个读 /etc/logrotate.d/* 里的应用规则 └── 对每条规则: ① 判断是否满足轮转条件(时间/大小) ② 把 access.log → access.log.1(旧的顺延 .2 .3 ...) ③ 可选:压缩成 .gz ④ 可选:通知服务重新打开日志文件(postrotate) ⑤ 超过保留份数的老日志直接删

关键点:轮转后原文件名被让出来,应用必须重新打开文件句柄,否则会一直往已轮转走的旧文件里写。这就是postrotate里常见systemctl reload xxx或kill -HUP的原因。

1.2 配置文件在哪

  • 主配置:/etc/logrotate.conf(全局默认)
  • 应用配置:/etc/logrotate.d/目录(每个服务一个文件,优先级更高)

1.3 最常用的指令

指令含义
daily/weekly/monthly轮转周期
rotate N保留 N 份旧日志
size 100M日志超过 100M 才轮转(和周期"或"关系)
compress/nocompress是否压缩旧日志
delaycompress延迟一轮再压缩(配合正在写的日志更稳)
missingok日志不存在也不报错
notifempty空日志不轮转
copytruncate拷贝后清空原文件(进程不重开文件也能用,但可能丢几字节)
create 0640 user group轮转后新建日志并指定权限属主
dateext用日期命名(access.log-20261012)而非序号
postrotate ... endscript轮转后执行脚本(如 reload 服务)
sharedscripts多个日志只执行一次 postrotate

1.4 自己写一个轮转配置(演示)

假设有个应用日志/var/log/myapp.log,要求:每天轮转、保留 7 份、压缩、空文件不转、轮转后让应用重开日志。

sudovim/etc/logrotate.d/myapp

写入:

/var/log/myapp.log { daily rotate 7 missingok notifempty compress delaycompress create 0640 root root dateext sharedscripts postrotate # 假设 myapp 支持 HUP 信号重开日志 /bin/kill -HUP $(cat /var/run/myapp.pid 2>/dev/null) 2>/dev/null || true endscript }

1.5 先"演习"再"真干"

# -d 调试模式:只模拟,不真改文件,用来检查配置写对没有sudologrotate-d/etc/logrotate.d/myapp# -vf 强制执行一次(v=verbose 看过程)sudologrotate-vf/etc/logrotate.d/myapp# 看结果ls-lh/var/log/myapp.log*# 预期:myapp.log myapp.log-20261012.gz

排错:如果logrotate -d报 “error: xxx” 一般是括号/路径写错;配完一定要-d跑一遍再等它自动执行。


二、Linux 启动链(开机到底发生了什么)

理解启动链,才能在"起不来"的时候知道卡在哪一环。主流发行版(CentOS 7+/Ubuntu)都是UEFI/BIOS → GRUB2 → 内核 → initramfs → systemd。

[加电] │ ▼ ① BIOS / UEFI (POST 自检,找启动设备) │ BIOS:读磁盘第 1 个扇区(MBR, 512B)里的引导程序 │ UEFI:读 ESP 分区里的 \EFI\BOOT\bootx64.efi ▼ ② GRUB2 引导加载程序 │ 显示启动菜单,加载内核与 initramfs 到内存 │ 配置:/boot/grub2/grub.cfg(不要手写,用命令生成) ▼ ③ 内核 (vmlinuz) 解压并启动,挂载 initramfs │ initramfs:临时根文件系统,内含驱动(尤其磁盘/raid/lvm 驱动) │ 作用:先让内核能认出真正的根设备 ▼ ④ 切换根 (switch_root) 到真实根文件系统 / ▼ ⑤ systemd 作为 PID 1 启动 │ 根据默认 target 拉起所有服务 ▼ ⑥ 到达默认 target multi-user.target → 命令行(相当于 runlevel 3) graphical.target → 图形界面(相当于 runlevel 5)

2.1 BIOS 与 UEFI 的区别(影响分区表)

BIOS + MBRUEFI + GPT
启动方式读 MBR 引导扇区读 ESP 分区 EFI 文件
磁盘容量≤ 2TB无限制
分区数最多 4 主分区128+
安全性弱支持 Secure Boot

顺带一查当前机器用的哪种固件:ls /sys/firmware/efi—— 有内容就是 UEFI,报错/为空就是传统 BIOS。

2.2 查看当前启动模式

# 查看默认启动到哪个模式:multi-user.target=命令行 / graphical.target=图形界面sudosystemctl get-default

2.3 GRUB 与 systemd 常用命令

# 重新生成 GRUB 配置(改了内核/磁盘后必跑)# Ubuntu/Debian:sudoupdate-grub# 临时切换到多用户(命令行)sudosystemctl set-default multi-user.target

2.4 拓展实战:忘记 root 密码?用救援模式进系统

讲完启动链,顺手解决一个最常被问到的真问题:密码忘了、进不去系统怎么办。核心思路就一句——在 GRUB 里打断内核启动,抢在 systemd 之前拿到 root 权限改密码。

操作(systemd 系发行版通用):

# ① 开机到 GRUB 菜单,光标停在内核上,按 e 编辑启动项# ② 找到以 linux(或 linux16)开头的行,在行尾追加:rd.break# ③ 按 Ctrl+X 启动,系统会停在 initramfs 紧急 shell# ④ 此时真实根以只读方式挂在 /sysroot,先重新挂载可写mount-oremount,rw /sysroot# ⑤ 切换根到真实系统chroot/sysroot# ⑥ 改密码passwdroot# ⑦ 开了 SELinux 的机器(CentOS/RHEL)必须打这个标记,否则策略不刷新会仍登不进touch/.autorelabel# ⑧ 退出并重启exitreboot

图形化如下:

要点:rd.break是在内核启动早期打断,所以能绕过登录先拿 root;/.autorelabel在 SELinux 开启的机器上不能省。这是"救援模式"最典型的一种用法——后面第九章还会讲 GRUB 损坏、fstab 写错等更多自救场景。


启动这关打通了:系统怎么起、起不来怎么救,心里都有数了。但光会"起得来"还不够——数据放哪、盘怎么加、满了怎么扩,才是日常运维真正的大头。下面进入存储世界:先看清一条目录背后到底链着多少层,再动手加盘、分区、上 LVM。

三、目录背后的完整映射(存储栈)

你cd /data/app看到的路径,背后是一条多层映射链。搞清楚它,磁盘问题就不再是黑盒:

物理磁盘 (Disk) │ /dev/sdb ▼ 分区 (Partition) │ /dev/sdb1 ← 分区表(GPT/MBR)把磁盘切成几块 ▼ [可选] 物理卷 PV → 卷组 VG → 逻辑卷 LV (LVM 层) │ /dev/vg_data/lv_data ← 把多块/多个分区"拼"成灵活的逻辑盘 ▼ 文件系统 (File System) │ mkfs.xfs / mkfs.ext4 ← 在块设备上建立目录树的索引结构 ▼ 挂载点 (Mount Point) │ mount /dev/... /data ← 把文件系统"挂"到目录树的某个节点 ▼ 应用看到的路径 /data/app/config.yaml ← 应用只认目录,不关心底下是块磁盘还是 LVM

一句话:应用看到的是"挂载点之后的路径",底层是磁盘还是 LVM 对它透明。出问题时要从下往上逐层验证。


四、添加磁盘后的三类证据互相验证:lsblk / blkid / findmnt

新加一块盘,光fdisk -l看一眼不够。三个命令各看一个维度,互相印证才放心:

命令看什么好比
lsblk块设备的层级树(盘→分区→LV)和挂哪了家族族谱
blkid每个设备的身份证(UUID、文件系统类型、PARTUUID)身份证
findmnt当前挂载关系(哪个设备挂在哪个目录)户口本

4.1 三连击演示

# ① 层级:看到 sdb 下面有 sdb1,以及它挂到 /datalsblk# NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT# sda 8:0 0 40G 0 disk# ├─sda1 8:1 0 1G 0 part /boot# └─sda2 8:2 0 39G 0 part# └─cl-root 253:0 0 37G 0 lvm /# sdb 8:16 0 100G 0 disk ← 新盘# └─sdb1 8:17 0 100G 0 part /data ← 已挂到 /data# ② 身份证:拿到 sdb1 的 UUID(持久挂载就靠它)blkid /dev/sdb1# /dev/sdb1: UUID="a1b2c3d4-..." TYPE="xfs" PARTUUID="..."# ③ 户口本:确认 /data 确实由该 UUID 的设备挂载findmnt /data# TARGET SOURCE FSTYPE OPTIONS# /data /dev/sdb1[xfs] xfs rw,relatime,...

4.2 怎么"互相验证"

排查思路(闭环):

  1. lsblk看到sdb1挂在/data;
  2. blkid /dev/sdb1拿到它的UUID=a1b2...;
  3. findmnt /data里 SOURCE 应显示同一设备、FSTYPE是 xfs;
  4. 三者对得上 → 磁盘、分区、文件系统、挂载点全链路健康。

常见坑:lsblk显示挂载了,但findmnt没有 → 多半是只写了 fstab 没mount -a,或挂载点目录被覆盖。


五、磁盘分区:GPT vs MBR 与实操步骤

5.1 选哪个

  • GPT:现代默认,支持 >2TB、128+ 分区、有备份分区表,UEFI 必选。用parted/gdisk。
  • MBR:老机器 / 传统 BIOS,≤2TB、最多 4 主分区,用fdisk。

5.2 用 parted 建 GPT 分区(推荐)

假设新盘是/dev/sdb,整盘划一个分区:

sudoparted/dev/sdb# (parted) mklabel gpt # 建 GPT 标签(会清掉旧表!)# (parted) mkpart primary xfs 1MiB 100% # 类型名只是标签,真正文件系统在 mkfs 定# (parted) align-check optimal 1 # 确认对齐(显示 1 aligned 即 OK)# (parted) print# (parted) quit

不想进交互模式,一条命令也行:

sudoparted-s/dev/sdb mklabel gptsudoparted-s/dev/sdb mkpart primary xfs 1MiB100%

5.3 查看分区结果

lsblk /dev/sdb

六、格式化、临时挂载与卸载

6.1 格式化(建立文件系统)

# XFS(CentOS/RHEL 默认,适合大文件/大容量)sudomkfs.xfs /dev/sdb1# EXT4(Ubuntu 默认,通用稳定)sudomkfs.ext4 /dev/sdb1

已格式化的盘想强制重格:mkfs.xfs -f /dev/sdb1/mkfs.ext4 -F /dev/sdb1。

6.2 临时挂载(重启失效)

sudomkdir-p/datasudomount/dev/sdb1 /data# 验证findmnt /datadf-h/data

6.3 卸载

# 按挂载点或设备都行sudoumount/data# 或sudoumount/dev/sdb1

卸载报target is busy?说明有进程正在用这个目录:

# 看谁在占用lsof+D /data# 或fuser-mv/data# 退出相关进程后再 umount;紧急情况可懒卸载(等进程关了再真卸)sudoumount-l/data

七、持久挂载与 /etc/fstab 详解

临时挂载重启就没了。要让它开机自动挂,得写/etc/fstab。

7.1 fstab 每行 6 个字段

# <设备> <挂载点> <类型> <选项> <dump> <pass> UUID=a1b2c3d4-... /data xfs defaults 0 0

字段说明
设备用UUID(最稳,blkid 获取)。也可用 /dev/sdb1,但盘序变了会挂错
挂载点必须已存在的空目录
类型xfs / ext4 / swap 等
选项defaults= rw,suid,dev,exec,auto,user,async 的集合
dump0=不备份(基本都写 0)
pass开机 fsck 顺序:根=1,其他=2,不检查=0

常用选项补充:

  • noatime:不更新访问时间,提升性能
  • nofail:盘不存在也不阻断启动(移动硬盘推荐)
  • defaults,noatime,nofail

7.2 实操:把 /data 持久化

# ① 拿 UUIDsudoblkid /dev/sdb1# 复制 UUID="a1b2c3d4-..." 里的那串# ② 编辑 fstab(务必先备份!)sudocp/etc/fstab /etc/fstab.baksudovim/etc/fstab# 追加一行:# UUID=a1b2c3d4-xxxx-xxxx /data xfs defaults,noatime 0 0# ③ 关键:用 mount -a 测试,不报错才说明写对了sudomount-aecho$?# 返回 0 = OKfindmnt /data# 确认已挂上

⚠️fstab 写错是启动失败的头号原因!改完务必mount -a验证,且一定先备份。


八、LVM 数据卷管理:创建与扩容完整步骤

LVM(逻辑卷管理)把"物理磁盘"抽象成"可随意伸缩的逻辑盘",加盘/扩容不用停机重分区。

8.1 概念对应

PV 物理卷 = 一块被 LVM 接管的磁盘/分区 (pvcreate) VG 卷组 = 多个 PV 凑成的存储池 (vgcreate / vgextend) LV 逻辑卷 = 从 VG 里切出来的"逻辑磁盘" (lvcreate / lvextend)

8.2 场景 A:从零新建 LVM 并挂载

# 假设新盘 /dev/sdc# ① 分区(LVM 建议整盘一个分区,类型 linux-lvm=0x8e 或留空)sudoparted-s/dev/sdc mklabel gptsudoparted-s/dev/sdc mkpart primary 1MiB100%# ② 创建 PVsudopvcreate /dev/sdc1sudopvs# 查看 PV 列表# ③ 创建 VGsudovgcreate vg_data /dev/sdc1sudovgs# 查看 VG# ④ 创建 LV(5G 示例)sudolvcreate-L5G-nlv_data vg_datasudolvs# 查看 LV# ⑤ 格式化 + 挂载sudomkfs.ext4 /dev/vg_data/lv_datasudomkdir-p/datasudomount/dev/vg_data/lv_data /data# ⑥ 持久化(拿 LV 的 UUID 写 fstab,同上节)sudoblkid /dev/vg_data/lv_data

8.3 场景 B:扩容(把磁盘"撑大")—— 重点

真实运维里最常见:业务涨了,/data 满了,要扩。

方式一:VG 里还有空闲空间

# 直接扩 LV + 扩文件系统一步到位(-r 自动 resize)sudolvextend-L+5G-r/dev/vg_data/lv_data# 没加 -r 的话,要手动扩文件系统:xfs:sudoxfs_growfs /data ext4:sudoresize2fs /dev/vg_data/lv_datadf-h/data# 确认容量已变大

方式二:VG 满了,先加新物理盘

# 新盘 /dev/sddsudopvcreate /dev/sdd1sudovgextend vg_data /dev/sdd1# 把新 PV 并入卷组vgs# 看 VG 的 VSize/VFree 变大了# 再扩 LV(自动扩文件系统)sudolvextend-L+10G-r/dev/vg_data/lv_datadf-h/data

方式三:虚拟机"在线扩容"已有虚拟磁盘

# 先在虚拟化平台把磁盘调大,系统里让内核重读分区表echo1|sudotee/sys/class/block/sdc/device/rescan# 用 growpart 把分区扩到整盘(CentOS: cloud-utils-growpart)sudogrowpart /dev/sdc1# 之后 pvresize 让 PV 认到新大小sudopvresize /dev/sdc1# 再走 lvextend -r 扩 LV

口诀:加盘 → pvcreate → vgextend → lvextend -r → 看 df。XFS 只能扩不能缩,ext4 可扩可缩(缩要先 umount 且风险高,谨慎)。

8.4 逐步检查

lsblk-fpvscan vgs lvscan findmnt--target....findmnt--target....df-hT....

总结

这一期我们把存储链路打通了:

  1. 日志轮转:logrotate 靠 cron 触发,按规则轮转+压缩,postrotate让应用重开日志;改完用-d演习。
  2. 启动链:UEFI/BIOS → GRUB2 → 内核+initramfs → systemd → target,配错卡哪环心里有数。
  3. 存储栈:disk → partition →(LVM: PV/VG/LV)→ 文件系统 → 挂载点 → 应用路径,应用只认挂载点之后。
  4. 三证验证:lsblk(层级) +blkid(UUID) +findmnt(挂载) 互相印证。
  5. 分区:GPT(>2TB/UEFI)用 parted,MBR 用 fdisk。
  6. 挂载:临时mount、持久写fstab(用 UUID,改前备份、mount -a验证)。
  7. LVM 扩容:加盘 →pvcreate→vgextend→lvextend -r→df确认。

本文命令在 CentOS 7+/Rocky 9 与 Ubuntu 22.04 验证思路一致,个别包名(如resize2fsvsxfs_growfs)按文件系统区分。动手前务必对生产数据备份。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询