09-磁盘管理
上一篇《网络配置》讲的是数据如何离开主机、经过路由和网络到达其他系统;本篇回到主机内部,讨论数据如何从应用写入文件系统,再经过逻辑卷、设备映射和块设备落到物理盘、虚拟盘或云盘。

从“看见一块盘”到“安全管理一条存储链”
上一篇《网络配置》讲的是数据如何离开主机、经过路由和网络到达其他系统;本篇回到主机内部,讨论数据如何从应用写入文件系统,再经过逻辑卷、设备映射和块设备落到物理盘、虚拟盘或云盘。
磁盘管理的危险不在于命令难,而在于同一条命令作用于错误设备时往往不可逆。mkfs、wipefs、pvcreate、parted、dd 和某些修复工具都可能在数秒内破坏元数据。生产操作必须先建立存储栈心智模型,确认设备身份、数据归属、依赖关系、备份和回滚边界,再执行变更。
本文采用“存储栈原理 + 配置 walkthrough + 扩容迁移 + 故障排查 runbook”的结构。示例以常见 util-linux、LVM2、ext4 和 XFS 工具为主。不同发行版、内核、文件系统和存储控制器版本可能存在差异,实施前应使用本机 man、--help 和发行版官方文档核对。
读完本文后,你应该能够:
- 使用
lsblk、blkid、findmnt、udevadm和/sys识别设备及其关系。 - 区分磁盘、分区、软件 RAID、LUKS、LVM、文件系统和挂载点。
- 安全创建 GPT 分区、LVM 逻辑卷和 ext4/XFS 文件系统。
- 正确编写并验证
/etc/fstab。 - 扩展虚拟盘、分区、PV、LV 和文件系统。
- 判断空间满、inode 满、I/O 延迟、只读文件系统、设备丢失和挂载失败。
- 理解在线扩容、离线检查、缩容和设备替换的风险边界。
1. Linux 存储不是一块盘,而是多层对象
应用通常只看到路径,例如 /var/lib/postgresql 或 /data。但路径下面可能经过多个层次:
应用目录
-> 挂载点
-> ext4 / XFS
-> LVM Logical Volume
-> LVM Volume Group
-> LVM Physical Volume
-> GPT 分区
-> 虚拟磁盘 / 云盘 / SAN LUN / 本地 SSD
还可能在中间加入 LUKS 加密、mdadm 软件 RAID、多路径设备或设备映射。排障和变更时,必须先知道当前主机实际使用了哪些层。
图中把应用到磁盘的层次串起来。扩容、迁移和故障修复必须逐层推进,不能看到 /dev/sdb 就假定它直接承载某个目录。
1.1 常见设备命名
| 设备形式 | 常见含义 |
|---|---|
/dev/sda、/dev/sdb |
SCSI/SATA/USB/虚拟块设备的传统名称 |
/dev/vda |
VirtIO 虚拟磁盘 |
/dev/nvme0n1 |
NVMe 设备 |
/dev/nvme0n1p1 |
NVMe 第一个分区 |
/dev/md0 |
mdadm 软件 RAID |
/dev/mapper/cryptdata |
device-mapper/LUKS 映射 |
/dev/mapper/vg_data-lv_app |
LVM 逻辑卷映射 |
/dev/dm-0 |
device-mapper 内核编号,不适合作为持久配置名称 |
设备名并不总是稳定。新增控制器、调整虚拟机硬件或改变发现顺序后,/dev/sdb 可能变成 /dev/sdc。持久挂载优先使用文件系统 UUID、LVM 路径或经过验证的稳定 by-id 路径。
1.2 先用 lsblk 建立拓扑
lsblk 来自 util-linux,用于列出块设备。建议显式指定输出列,避免脚本依赖不同版本的默认列。
lsblk -e 7 \
-o NAME,KNAME,PATH,TYPE,SIZE,FSTYPE,FSVER,LABEL,UUID,MOUNTPOINTS,MODEL,SERIAL
其中:
NAME展示树形名称;KNAME是内核设备名;TYPE可区分 disk、part、lvm、crypt、raid;FSTYPE与UUID来自文件系统或签名探测;MOUNTPOINTS展示一个设备可能对应的多个挂载点;MODEL、SERIAL有助于确认硬件或虚拟盘身份。
设备刚热添加后,udev 信息可能尚未完全就绪。自动化脚本中可以在读取前执行:
udevadm settle
lsblk --json -o NAME,PATH,TYPE,SIZE,FSTYPE,UUID,MOUNTPOINTS
结构化输出比解析对齐文本更可靠。
1.3 用 findmnt 从目录反查设备
如果问题从目录开始,例如 /var 满了,应优先从挂载点反查:
findmnt /var
findmnt -T /var/lib/app
findmnt -no SOURCE,FSTYPE,OPTIONS,TARGET /var
再沿设备向下查看:
lsblk -f
lsblk -s /dev/mapper/vg_system-lv_var
lvs -a -o +devices
pvs -o pv_name,vg_name,pv_size,pv_free
lsblk -s 以反向依赖顺序显示设备链,适合从 LV 或文件系统回溯到底层磁盘。
1.4 不要把 df 和 du 混为一谈
df 从文件系统视角统计已用块和可用块;du 遍历目录项统计可见文件大小。两者不一致时,可能存在:
- 文件已删除但仍被进程打开;
- 目录被另一个文件系统覆盖挂载;
- 稀疏文件的逻辑大小与实际占用不同;
- 快照、保留块、元数据或文件系统开销;
- 权限导致
du无法遍历所有目录。
基础检查:
df -hT
df -ih
du -xhd1 /var 2>/dev/null | sort -h
lsof +L1
df -i 用于检查 inode。大量小文件可能在容量仍有剩余时耗尽 inode,表现为“设备上没有空间”。
2. 变更前先做设备身份确认
磁盘事故中最常见的错误不是命令失败,而是命令成功作用在错误设备上。生产变更前应保存证据。
audit_dir="$HOME/storage-audit-$(date +%F-%H%M%S)"
mkdir -p "$audit_dir"
lsblk -e 7 -o NAME,KNAME,PATH,TYPE,SIZE,FSTYPE,LABEL,UUID,MOUNTPOINTS,MODEL,SERIAL \
> "$audit_dir/lsblk.txt"
blkid > "$audit_dir/blkid.txt" 2>&1
findmnt --real > "$audit_dir/findmnt.txt"
df -hT > "$audit_dir/df-hT.txt"
df -ih > "$audit_dir/df-inode.txt"
pvs > "$audit_dir/pvs.txt" 2>&1
vgs > "$audit_dir/vgs.txt" 2>&1
lvs -a -o +devices > "$audit_dir/lvs.txt" 2>&1
cat /etc/fstab > "$audit_dir/fstab.txt"
dmesg -T | tail -300 > "$audit_dir/dmesg-tail.txt"
然后回答:
- 目标设备的序列号、容量、总线和云平台磁盘 ID 是什么?
- 设备是否已有分区、文件系统、LVM、RAID 或 LUKS 签名?
- 是否被挂载、被进程打开、作为 swap 或作为 RAID/LVM 成员?
- 数据是否有备份,最近一次恢复是否验证?
- 变更失败时,能回滚到哪一层?
检查签名时可使用只读探测:
sudo wipefs --no-act /dev/sdb
sudo blkid -p /dev/sdb
不要把 wipefs 不带 --no-act 用作“查看命令”。删除签名属于破坏性操作。
3. 分区:GPT 是现代服务器的默认选择
分区表描述磁盘上的分区边界。现代服务器通常优先使用 GPT,原因包括支持大容量磁盘、分区数量更灵活,并保留主分区表和备份信息。MBR 仍可能出现在旧系统、兼容环境和某些启动场景中。
3.1 查看分区表
sudo fdisk -l /dev/sdb
sudo parted /dev/sdb print
sudo sfdisk --dump /dev/sdb
变更前可备份分区布局:
sudo sfdisk --dump /dev/sdb > "$audit_dir/sdb-partition-table.sfdisk"
对于 GPT,也可按环境使用 sgdisk --backup。恢复工具必须提前验证,不要在事故现场第一次使用。
3.2 创建新 GPT 分区
以下假设 /dev/sdb 是已确认的新空盘,且不存在需要保留的数据:
sudo parted -s /dev/sdb mklabel gpt
sudo parted -s /dev/sdb mkpart primary 1MiB 100%
sudo partprobe /dev/sdb
udevadm settle
lsblk -f /dev/sdb
保留 1 MiB 起始对齐通常适用于现代存储。执行前必须再次检查设备路径。
如果分区用于 LVM,可设置对应标志或分区类型;但 LVM 能直接使用整盘,也能使用分区。企业应统一规范,避免同一环境一部分整盘做 PV、一部分分区做 PV,增加识别难度。
3.3 扩展分区的边界
虚拟化或云平台扩展底层磁盘后,Linux 可能先看到新的磁盘容量,但分区仍保持原大小。典型流程是:
扩展云盘/虚拟盘
-> 让内核重新识别容量
-> 扩展目标分区
-> 扩展 PV
-> 扩展 LV
-> 扩展文件系统
每一步都要验证。不能看到云控制台容量变大,就直接执行 resize2fs。
重新识别方式取决于设备类型和平台。可以先比较:
lsblk
sudo blockdev --getsize64 /dev/sdb
cat /sys/class/block/sdb/size
某些环境需要重新扫描 SCSI 总线、控制器或重启实例。具体方法应遵循平台官方文档,避免对错误 host 扫描路径。
4. LVM:用 PV、VG、LV 解耦物理容量和文件系统
LVM 将底层块设备抽象为 Physical Volume,将多个 PV 汇聚成 Volume Group,再从 VG 分配 Logical Volume。它的价值是容量池化、在线扩展、设备迁移和灵活命名,而不是替代备份。
4.1 观察 LVM 状态
sudo pvs -o pv_name,vg_name,pv_size,pv_free,pv_uuid
sudo vgs -o vg_name,vg_size,vg_free,pv_count,lv_count
sudo lvs -a -o lv_name,vg_name,lv_size,lv_attr,segtype,devices
lvs -o +devices 非常重要,它能显示 LV 的数据实际位于哪些 PV 上。执行 pvmove、移除磁盘或排查丢盘时,不能只看 LV 名称。
4.2 创建 PV、VG 和 LV
以下假设 /dev/sdb1 是已确认、无需保留数据的新分区:
sudo pvcreate /dev/sdb1
sudo vgcreate vg_data /dev/sdb1
sudo lvcreate -L 100G -n lv_app vg_data
验证:
sudo pvs
sudo vgs
sudo lvs -a -o +devices
lsblk -f
生产环境命名应体现用途,而不是只用 vg0/lv0。例如 vg_data/lv_postgres、vg_logs/lv_audit 更容易审计。但命名也不应包含频繁变化的服务器名或项目临时代号。
4.3 VG 不等于冗余
把两块磁盘加入同一个 VG,只是汇聚容量,不自动提供 RAID 冗余。如果任一 PV 丢失,而 LV 的 extents 分布在该 PV 上,LV 可能部分或全部不可用。
需要冗余时,应在底层存储、硬件 RAID、mdadm、LVM RAID、SAN 或云盘复制层明确设计。不要把“VG 有两块盘”误认为“双盘保护”。
4.4 LVM 元数据备份
LVM 通常会在 /etc/lvm/backup 和 /etc/lvm/archive 保存元数据文本副本。重要变更前可以显式备份:
sudo vgcfgbackup vg_data
sudo ls -l /etc/lvm/backup /etc/lvm/archive
元数据备份不能恢复文件数据,但在某些 VG 元数据损坏场景中非常关键。应把这些文件纳入系统配置备份。
5. 创建文件系统:格式化之前要最后确认一次
mkfs 会创建新文件系统并覆盖关键元数据。执行前至少运行:
lsblk -f /dev/mapper/vg_data-lv_app
findmnt -S /dev/mapper/vg_data-lv_app
sudo wipefs --no-act /dev/mapper/vg_data-lv_app
确认目标未挂载、无现有数据、无业务依赖。
5.1 ext4
sudo mkfs.ext4 -L appdata /dev/mapper/vg_data-lv_app
ext4 支持在线扩容。缩容通常要求离线,并且必须先缩文件系统再缩块设备;顺序错误会直接破坏数据。生产环境中,与其在线上做 ext4 缩容,通常更稳妥的是创建新卷、迁移数据、切换挂载并保留回滚。
5.2 XFS
sudo mkfs.xfs -L appdata /dev/mapper/vg_data-lv_app
XFS 支持挂载状态下扩容,常用 xfs_growfs。传统 XFS 运维实践中不支持缩小现有文件系统,因此缩容通常采用新建较小文件系统、复制数据和切换挂载的方式。
5.3 选择 ext4 还是 XFS
| 维度 | ext4 | XFS |
|---|---|---|
| 通用性 | 广泛支持,适合多数 Linux 工作负载 | 企业服务器和大文件/高并发场景常见 |
| 在线扩容 | 支持 | 支持 |
| 缩容 | 可离线缩容,但风险高 | 通常不支持原地缩容 |
| 修复工具 | e2fsck |
xfs_repair |
| 配额 | 支持 | 支持,需按挂载参数和发行版配置 |
文件系统选择不能只依据“哪个快”。还要考虑发行版默认、运维经验、备份工具、快照、恢复流程、工作负载和厂商支持。
6. 挂载与 fstab:持久配置必须先验证
创建挂载点:
sudo install -d -o root -g root -m 0755 /data/app
临时挂载:
sudo mount /dev/mapper/vg_data-lv_app /data/app
findmnt /data/app
df -hT /data/app
写入测试前先确认目录原来没有被其他数据占用。挂载会遮住挂载点目录原有内容,卸载后原内容才会重新出现。
6.1 使用 UUID
查询 UUID:
sudo blkid /dev/mapper/vg_data-lv_app
/etc/fstab 示例:
UUID=<filesystem-uuid> /data/app xfs defaults,noatime 0 0
ext4 示例:
UUID=<filesystem-uuid> /data/app ext4 defaults,noatime 0 2
最后两个字段分别与 dump 和 fsck 顺序有关。根文件系统通常使用 1,其他 ext 系列文件系统常用 2;XFS 常用 0。应遵循发行版规范,不要机械复制。
6.2 修改 fstab 后不要直接重启验证
先执行:
sudo findmnt --verify --verbose
sudo systemctl daemon-reload
sudo mount -a
findmnt /data/app
如果 mount -a 报错,应立即修正。错误的 fstab 可能导致启动进入紧急模式。
对于非关键网络或可移除存储,可以考虑 nofail、x-systemd.automount、设备超时等选项,但这些选项会改变启动和故障语义。核心业务数据盘不应简单加 nofail 掩盖丢盘。
6.3 权限属于文件系统内容,不属于挂载命令
挂载完成后,根据应用账号设置:
sudo chown appuser:appgroup /data/app
sudo chmod 0750 /data/app
如果卸载后发现权限“变化”,可能是你看到的其实是底层挂载点目录,而不是文件系统根目录。排查时始终用 findmnt -T 确认当前路径属于哪个文件系统。
7. LVM 在线扩容完整 walkthrough
扩容看起来简单,但必须按层次执行。下面假设:
- 云平台已将
/dev/sdb从 200 GiB 扩展到 300 GiB; /dev/sdb1是 LVM PV;- VG 为
vg_data; - LV 为
lv_app; - 文件系统挂载到
/data/app。
图中把扩盘、PV、VG、LV 和文件系统分开。扩容通常可在线完成,但每一层都要确认实际容量和业务状态。
7.1 变更前检查
findmnt /data/app
df -hT /data/app
lsblk -f
pvs
vgs
lvs -a -o +devices
确认备份和恢复点,检查业务是否允许变更,记录当前 I/O 和延迟。
7.2 确认内核看到新磁盘容量
lsblk /dev/sdb
sudo blockdev --getsize64 /dev/sdb
如果容量未变化,应先按虚拟化、云平台或存储厂商文档完成重扫。不要继续扩分区。
7.3 扩展分区
如果 PV 位于第一个分区,可按环境使用 growpart、parted 或其他受支持工具。以 growpart 为例:
sudo growpart /dev/sdb 1
sudo partprobe /dev/sdb
udevadm settle
lsblk /dev/sdb
growpart 并非所有系统默认安装,命令行为要以本机帮助和发行版包为准。使用前必须备份分区表。
7.4 扩展 PV
sudo pvresize /dev/sdb1
sudo pvs -o pv_name,pv_size,pv_free,vg_name
sudo vgs
如果 pvresize 后 VG 没有出现预期空闲空间,应停止并检查分区和设备容量,不要直接改 LV。
7.5 扩展 LV
扩展 50 GiB:
sudo lvextend -L +50G /dev/vg_data/lv_app
使用全部剩余空间:
sudo lvextend -l +100%FREE /dev/vg_data/lv_app
验证:
sudo lvs -a -o lv_name,vg_name,lv_size,devices
lsblk
+100%FREE 会消耗 VG 所有剩余空间,可能让后续快照、临时扩容和其他 LV 无空间可用。生产环境通常应保留一定 VG 空闲容量。
7.6 扩展文件系统
ext4:
sudo resize2fs /dev/vg_data/lv_app
XFS 必须针对已挂载路径执行:
sudo xfs_growfs /data/app
验证:
df -hT /data/app
findmnt /data/app
lsblk -f
有些 lvextend 版本支持 -r 调用 fsadm 或文件系统工具同步扩容,例如:
sudo lvextend -r -L +50G /dev/vg_data/lv_app
生产环境使用前应确认发行版支持的文件系统、工具链和日志输出。分步执行虽然多几条命令,但更容易在每层验证。
8. 新增磁盘扩展 VG
如果不是扩原盘,而是新增 /dev/sdc:
lsblk -f /dev/sdc
sudo wipefs --no-act /dev/sdc
确认新盘无数据后创建 PV:
sudo pvcreate /dev/sdc
sudo vgextend vg_data /dev/sdc
sudo pvs
sudo vgs
然后按需要扩 LV 和文件系统。
8.1 注意数据分布
新增 PV 后扩展 LV,新的 extents 可能落在新盘上。此后 LV 依赖多块盘,任何一块丢失都可能影响数据。底层是否具备冗余必须明确。
8.2 安全移除 PV
不能直接从系统删除仍承载 extents 的 PV。先看:
sudo pvs -o pv_name,vg_name,pv_size,pv_free,pv_used
sudo lvs -a -o +devices
如果 VG 有其他足够空间,可迁移:
sudo pvmove /dev/sdc
sudo vgreduce vg_data /dev/sdc
sudo pvremove /dev/sdc
pvmove 可能产生大量 I/O,应在变更窗口监控延迟和业务。执行前确认目标 PV 空间、冗余、备份和中断恢复能力。
9. 空间满:先区分容量、inode 和隐藏占用
9.1 容量满
df -hT
du -xhd1 /var | sort -h
du -xhd1 /data | sort -h
-x 避免跨越其他文件系统。定位到大目录后逐层下钻,不要直接在根目录执行无边界的全盘 du 影响业务。
9.2 inode 满
df -ih
find /var/spool/app -xdev -type f -printf '%h\n' 2>/dev/null \
| sort | uniq -c | sort -n | tail
大量小文件常见于缓存、队列、邮件、临时目录、日志切分和任务失败重试。删除文件前要先确认应用语义,避免破坏队列或状态。
9.3 删除文件仍不释放空间
sudo lsof +L1
如果进程仍持有已删除文件,空间会在文件描述符关闭后释放。优先让应用重新打开日志、执行受支持的 reload,或在窗口内重启服务。不要直接操作 /proc/<pid>/fd 指向的文件,除非有明确的取证和恢复方案。
9.4 日志治理
检查 journal:
journalctl --disk-usage
检查 logrotate:
sudo logrotate -d /etc/logrotate.conf
不要在生产中未经评估直接删除活跃数据库、容器运行时或审计日志。正确做法是确定增长源、保留要求、轮转策略和容量告警。
10. I/O 性能:容量正常也可能很慢
磁盘性能问题需要区分设备延迟、队列、吞吐、文件系统、应用访问模式和底层共享存储争用。
10.1 iostat
安装 sysstat 后可使用:
iostat -xz 1 10
常见观察项包括:
r/s、w/s:每秒读写请求;rkB/s、wkB/s:吞吐;await:请求平均等待时间;aqu-sz:平均队列长度;%util:设备忙碌程度。
不能只看 %util。不同设备、NVMe、多队列和虚拟化环境中,指标含义需要结合延迟、吞吐和业务 SLA。高延迟也可能来自 SAN、云盘限速、快照、备份或邻居工作负载。
10.2 pidstat 与进程定位
pidstat -d 1 10
sudo iotop -oPa
工具未安装时,可结合 /proc/<pid>/io、服务指标和应用日志。不要在事故中为了安装工具触发大量包升级。
10.3 云盘和虚拟盘的特殊限制
云盘常将性能与容量、规格、突发额度或实例带宽绑定。虚拟机内部看到的延迟可能来自:
- 云盘 IOPS/吞吐上限;
- 实例总存储带宽上限;
- 突发额度耗尽;
- 快照或备份任务;
- 多盘共享控制器;
- 宿主机或存储网络问题。
排查时要同时查看主机指标和平台侧磁盘指标。
11. 设备健康、内核错误与 SMART
11.1 先看内核日志
dmesg -T | grep -Ei 'error|fail|timeout|reset|I/O|nvme|scsi|ata|ext4|xfs'
journalctl -k --since "-2 hours"
重点关注:
- I/O error;
- command timeout;
- controller reset;
- link reset;
- filesystem error;
- device offline;
- multipath path failed;
- NVMe controller reset。
同一错误反复出现时,不应只清日志或重启。要关联设备序列号、控制器、虚拟磁盘和存储平台事件。
11.2 SMART
本地 SATA/SAS/NVMe 设备可按硬件支持使用 smartmontools:
sudo smartctl -a /dev/sda
sudo smartctl -x /dev/nvme0
虚拟盘、硬件 RAID 后的逻辑盘和 SAN LUN 可能无法直接提供完整 SMART 信息,需要使用控制器、阵列或云平台工具。不要因为 smartctl 无数据就判断磁盘健康。
11.3 发现介质错误后的原则
- 优先保护数据和业务,不先追求“把盘修好”。
- 停止非必要写入,降低进一步损坏。
- 保存日志、SMART、阵列和平台事件。
- 确认冗余是否仍健康,避免第二块盘同时失败。
- 按存储架构执行替换、重建或迁移。
- 从备份验证关键数据,而不是只看 RAID 重建完成。
12. 文件系统只读、挂载失败与修复边界
文件系统检测到严重错误时,可能重新挂载为只读以保护数据。此时应用会出现写入失败、数据库停机或日志异常。
图中把设备消失、空间满、I/O 变慢和挂载失败分开。修复前先确认设备、备份和业务影响,避免对错误设备运行破坏性工具。
12.1 先确认现象
findmnt -no SOURCE,FSTYPE,OPTIONS,TARGET /data/app
dmesg -T | tail -200
journalctl -k --since "-1 hour"
如果挂载选项中出现 ro,继续判断是人为只读挂载,还是文件系统错误触发。
12.2 ext4 检查
e2fsck 通常应对未挂载文件系统执行。不能对正在读写的生产文件系统直接强制检查。
sudo umount /data/app
sudo e2fsck -f /dev/vg_data/lv_app
根文件系统或无法卸载的业务卷需要进入维护模式、救援环境或从其他系统启动。执行前应有备份,并保存错误信息。
12.3 XFS 检查
先使用只读检查模式:
sudo umount /data/app
sudo xfs_repair -n /dev/vg_data/lv_app
确认输出和风险后,按官方文档决定是否执行实际修复。xfs_repair -L 会清除日志,可能丢失未完成的元数据更新,应视为高风险最后手段,不能作为“挂载失败就执行”的常规命令。
12.4 挂载失败常见原因
- fstab UUID 写错或设备尚未出现;
- LVM VG 未激活;
- LUKS 未解锁;
- 文件系统类型写错;
- 挂载点不存在;
- 文件系统需要离线修复;
- 网络存储不可达;
- systemd mount unit 依赖或超时错误;
- 同一文件系统已挂载到其他位置;
- 内核不支持对应文件系统或模块未加载。
排查:
sudo findmnt --verify --verbose
sudo mount -av
systemctl --failed
journalctl -b -p warning
lsblk -f
sudo vgchange -ay
不要为了让系统启动而长期给核心数据盘加 nofail。这会把明确故障变成应用在空目录中写入数据的隐蔽事故。
13. 缩容:比扩容危险得多
扩容通常在末端增加空间;缩容要保证将要移除的区域没有有效数据,并要求文件系统、LV、分区和底层设备按严格顺序缩小。
13.1 XFS 缩容
常见生产实践不进行原地 XFS 缩容,而是:
- 创建新的较小 LV 和 XFS;
- 挂载到临时目录;
- 使用
xfsdump/xfsrestore、rsync或应用级工具迁移; - 停止写入并做增量同步;
- 切换挂载;
- 验证业务;
- 保留旧卷一段回滚时间。
13.2 ext4 缩容
ext4 可离线缩容,但顺序必须是先缩文件系统,再缩 LV。任何估算或命令错误都可能破坏数据。生产环境仍建议优先采用新卷迁移方案。
13.3 不要用 lvreduce 猜大小
lvreduce 缩小块设备不会理解文件系统中哪些块仍在使用。即使工具提供 --resizefs,也应先在相同发行版和文件系统版本的测试环境验证,并确保备份和停机窗口。
14. 迁移数据盘的安全流程
假设要把 /data/app 从旧 LV 迁移到新存储:
- 创建新设备、文件系统和临时挂载点。
- 验证容量、权限、挂载选项和性能。
- 首次在线复制大部分数据。
- 记录硬链接、ACL、扩展属性、稀疏文件和 SELinux 标签需求。
- 进入变更窗口,停止应用写入。
- 执行最终增量复制。
- 校验文件数量、容量、关键哈希和应用一致性。
- 更新 fstab 或挂载单元。
- 切换挂载并启动应用。
- 验证业务、日志、监控、备份和重启。
- 保留旧卷只读,直到回滚窗口结束。
rsync 示例需要按数据特征调整:
sudo rsync -aHAXS --numeric-ids --info=progress2 \
/data/app/ /mnt/new-app/
数据库文件不能在运行状态下简单复制并假设一致。应使用数据库备份、复制、快照一致性或厂商支持的迁移方法。
15. Swap 也是块设备管理的一部分
查看:
swapon --show
free -h
cat /proc/swaps
swap 可以是分区、LV 或文件。添加 swap file:
sudo fallocate -l 4G /swapfile
sudo chmod 0600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
swapon --show
持久化:
/swapfile none swap sw 0 0
某些文件系统、快照、加密或休眠场景对 swap file 有额外要求。实施前按发行版和内核文档验证。swap 不能替代内存容量规划;持续高 swap 和频繁换页通常表示内存压力或应用配置问题。
16. 自动化脚本的安全设计
磁盘自动化比人工操作更需要防误伤。脚本至少应:
- 使用
lsblk --json等结构化输出; - 根据序列号、WWN、云盘 ID 和预期容量确认设备;
- 拒绝处理根盘、已挂载设备、已有签名设备;
- 在破坏性操作前要求显式参数和二次确认;
- 输出计划但默认不执行,支持 dry-run;
- 检查命令退出码并在每层验证;
- 记录变更前后状态;
- 不使用模糊匹配选择
/dev/sd*; - 对并发执行加锁;
- 失败后停止,不自动尝试更多破坏性修复。
示例防护思路:
target=/dev/disk/by-id/<expected-device-id>
test -b "$target" || exit 1
findmnt -S "$target" && exit 1
lsblk --json "$target"
sudo wipefs --no-act "$target"
这段代码仍不足以直接格式化设备,但展示了自动化应先验证事实,而不是根据“第二块盘大概是 sdb”执行。
17. 生产磁盘变更检查表
变更前
- [ ] 已确认业务系统、数据负责人和变更窗口。
- [ ] 已保存
lsblk、findmnt、LVM、fstab 和内核日志基线。 - [ ] 已通过序列号、WWN 或平台磁盘 ID 确认目标。
- [ ] 已检查设备现有签名、挂载、swap、RAID、LUKS 和 LVM 关系。
- [ ] 已有可用备份,并明确恢复方法。
- [ ] 已评估 I/O 影响、停机和回滚边界。
变更中
- [ ] 每完成一层都验证容量和状态。
- [ ] 没有使用未经确认的通配设备名。
- [ ] 没有在挂载文件系统上运行离线修复工具。
- [ ] 没有把 VG 容量池误认为冗余。
- [ ] 没有消耗全部 VG 空间而忽略后续需求。
- [ ] 日志和业务指标持续正常。
变更后
- [ ]
lsblk、pvs/vgs/lvs、findmnt、df结果一致。 - [ ]
/etc/fstab已通过findmnt --verify和mount -a。 - [ ] 应用可以读写,权限和 SELinux 上下文正确。
- [ ] 监控容量、inode、延迟和设备健康。
- [ ] 备份策略已覆盖新卷。
- [ ] 已执行重启或演练验证持久挂载。
- [ ] CMDB、容量记录和变更记录已更新。
18. 故障排查总路径
面对磁盘告警时,建议按以下顺序:
- 确认影响范围:单目录、单 LV、单盘、整台主机还是存储平台。
- 确认时间线:扩容、快照、备份、重启、补丁或硬件事件是否刚发生。
- 确认设备拓扑:
lsblk、findmnt、LVM、RAID、LUKS、多路径。 - 确认容量:块空间、inode、VG 空间、云盘配额。
- 确认 I/O:延迟、队列、吞吐、错误和超时。
- 确认文件系统:挂载选项、只读、内核错误、离线检查需求。
- 确认进程占用:删除文件、打开句柄、写入源。
- 确认底层健康:SMART、控制器、阵列、SAN、云平台事件。
- 先隔离和备份,再修复:避免故障扩大。
- 恢复后验证业务和数据:不能只看设备重新出现。
19. 总结
Linux 磁盘管理的核心不是掌握更多破坏性命令,而是准确识别存储栈,并按层次完成变更。应用路径下面可能是文件系统、LVM、LUKS、RAID、分区和虚拟磁盘;任何扩容、迁移或修复都必须知道自己正在操作哪一层。
日常管理应形成几个习惯:
- 从
findmnt和lsblk建立事实,不凭设备名猜测。 - 使用 UUID、LVM 路径和稳定设备标识进行持久配置。
- 把分区、PV、VG、LV 和文件系统视为独立层,逐层验证。
- 扩容通常可在线完成,缩容和修复应按高风险离线变更处理。
- 空间满要区分容量、inode、删除文件占用和挂载覆盖。
- I/O 慢要结合主机、设备、平台和应用指标。
- 备份、冗余和快照解决不同问题,不能互相替代。
- 所有破坏性操作前都应确认设备身份、业务依赖和恢复能力。
下一篇将进入《日志管理》,把 systemd journal、传统日志文件、日志轮转、集中采集、审计和容量治理串成一条完整运维链路。
参考资料
- util-linux
lsblk(8):https://man7.org/linux/man-pages/man8/lsblk.8.html - util-linux
findmnt(8):https://man7.org/linux/man-pages/man8/findmnt.8.html - util-linux
mount(8):https://man7.org/linux/man-pages/man8/mount.8.html - LVM2 project documentation:https://sourceware.org/lvm2/
- Linux kernel ext4 documentation:https://docs.kernel.org/filesystems/ext4/index.html
- Red Hat Enterprise Linux 9, Managing storage devices:https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/managing_storage_devices/index
本文最后更新于 2026-06-15