「按错机器的回车键」一次 parted 误操作与零损失复盘

一次误操作把香港宿主机 A 的分区命令敲进英国机器 B。内核「不采纳新表」、新旧分区几何完全一致,最终结果是零损失。这篇复盘记录事故经过、取证思路、结论与复盘清单。

生产环境里最危险的操作,多数不在命令本身,而在执行命令时的上下文。多台机器的终端同时打开时,设备名相同、命令相同,回车键落下之前看不出差别;落下之后,事故与复盘开始。

事故经过:回车键落在了另一台机器上

事情发生在给香港宿主机 A 重建 RAID 的当晚。按计划,A 机的 nvme1n1(1.5T)要重建 GPT 分区表,并划出一个 bcache 缓存分区,后续作为新 RAID 的缓存盘。预案中的两条命令:

parted -s /dev/nvme1n1 mklabel gpt
parted -s /dev/nvme1n1 mkpart bcache-cache 1MiB 100%

问题在执行环境。当晚多台机器的终端同时打开,A 机的命令与 B 机的终端混在一起。命令执行的目标是英国机器 B 的终端,不是香港 A 机的 1.5T 盘。B 机同样有 /dev/nvme1n1,容量 3.5T,盘上不是待重建的空盘,而是一套在线服务的 LVM。

「按错机器的回车键」,就这么发生了。事后复盘,执行前多看一眼 lsblk、以磁盘大小做指纹,1.5T 与 3.5T 的差别在输出里一目了然,这次误操作在回车之前就能拦下。

这块盘上装着什么

英国机器 B 的 /dev/nvme1n1 是 3.5T 生产盘,盘上是完整的 LVM 结构:PV nvme1n1p1 属于卷组 vg_vmdata;卷组由 2 个 3.49T 的 PV 组成 7T 的 LV vmdata,xfs 文件系统挂载在 /ssd,已用 3.5T。

这块盘不是可随意重写的空盘,而是装着 3.5T 业务数据的生产盘。mklabel gpt 已写入。按照常规路径,分区表应已被重写,vg_vmdata 与 /ssd 随时可能从系统中消失。LVM 处于在线状态,卷组内数据仍在正常读写,破坏分区布局或 PV 签名的动作可能在极短时间内打崩整个文件系统。

当时的评估:盘上的 3.5T 数据可能毁于这一次回车。

取证:内核没有采纳新表

命令写入后,parted 给出报错,大意是:

Partition(s) 1 on /dev/nvme1n1 have been written, but we have been unable to inform the kernel of the change, probably because it/they are in use... old partition(s) will remain in use.

这是第一道防线。分区正被 LVM 占用,内核无法同步新分区表,内核继续使用旧分区表,LVM 全程在线。磁盘上写入了新表,系统仍按旧表运行。

此时先取证,不重启。sysfs 里的 start 和 size 两个文件记录内核当前采用的旧分区几何,不受磁盘上新写入的 GPT 影响,是判断新旧是否一致的依据:

cat /sys/block/nvme1n1/nvme1n1p1/start
# 2048
cat /sys/block/nvme1n1/nvme1n1p1/size
# 7501473792

拿到旧分区几何后,用 fdisk 读取磁盘上新写入的 GPT 做对比:

fdisk -l /dev/nvme1n1
# start 2048 / sectors 7501473792

新旧几何完全一致。mkpart bcache-cache 1MiB 100% 从 1MiB 处起、用满整盘,在 3.5T 盘上重建出的单分区与原分区几何相同。1MiB 对齐换算成扇区为 2048,7501473792 扇区约合 3.49T,与原 PV 大小一致。

结论:零损失,以及它为什么成立

取证结果:零损失。

数据未丢失,有三层原因叠加:

  1. LVM PV 数据从分区起始(2048 扇区)开始。分区几何未变,PV 签名与数据位置仍然有效。LVM 不依赖分区类型标志,只识别 PV 头部的签名,签名仍位于原偏移。
  2. mklabel gpt 只写磁盘头尾的 GPT 表区域,未触碰中间的数据区。GPT 主表位于磁盘头部、备份表位于尾部,单分区数据从 2048 扇区开始,中间的数据区未被改动。
  3. vgcfgbackup vg_vmdata 补了一份 LVM 元数据备份,即使发生最坏情况,仍有重建元数据的备份。

误操作写下去的内容与盘上原有内容一致,真正立即生效的内核视图从头到尾未切换。物理层面未碰数据,逻辑层面 PV 仍可识别,内核坚持旧分区表,三层条件叠加,本次误操作未演变成事故。需要承认:「分区几何恰好一致」是零损失的重要条件,这一条件来自巧合,不是计划。

收尾修复:分区标志与备份

新 GPT 的分区几何与旧表一致,修复动作很小。分区类型标志可一并还原:

parted -s /dev/nvme1n1 set 1 lvm on

这一步属于装饰:LVM 靠签名识别 PV,不依赖分区类型标志。必要动作是确认 vgcfgbackup 的备份已生成,并将备份保存到本机之外。备份与原盘放在同一台机器上,出故障时会同时消失,异地存放才有意义。

本次无损的结果依赖内核拒绝采纳新表和分区几何的巧合,不依赖操作本身的安全性。这些偶然条件需要转化为复盘清单里的纪律。

复盘清单

本次事故的教训收敛为以下四条:

  • 多台机器同时开终端时,危险命令执行前先「验明正身」:lsblk /dev/<目标盘> -o NAME,SIZE,TYPE,用磁盘大小做指纹(A 机 1.5T,B 机 3.5T)。
  • 分区表被占用时,内核不会采纳新表。这一机制是本次零损失的关键,不能依赖,它来自巧合。
  • 出事后先取证(sysfs 中的旧分区 start/size 是依据),再决定修复方案,不立即重启。
  • 生产磁盘先备份 LVM 元数据(vgcfgbackup)与分区表(sgdisk --backup)。