跳转至

CentOS 7 拆分 SSD 后启动失败问题完整排查与解决手册

服务器:HP R620 | 系统:CentOS 7.9 x86_64 | 内核:3.10.0-1160.* 日期:2026-08-24 ~ 2026-08-25


一、问题现象

1.1 触发场景

用户将原本合并为一个 LVM 卷组的 1 块 SSD + 2 块 HDD(RAID 0) 尝试拆分,期望把 SSD 独立出来另作他用(创建 etcd 专用 LV)。操作过程中要求"每步都要有备份",但操作进行到一半重启后,系统无法启动,进入 dracut 紧急模式。

1.2 报错现象(启动时)

dracut-initqueue[xxx]: Warning: dracut-initqueue timeout - starting timeout scripts
...(重复刷屏数百行)
dracut-initqueue[xxx]: Warning: Could not boot.
dracut-initqueue[xxx]: Warning: /dev/centos_hp-r620/swap does not exist
Starting Dracut Emergency Shell...
Warning: /dev/centos_hp-r620/swap does not exist
Generating "/run/initramfs/rdsosreport.txt"
Entering emergency mode. Exit the shell to continue.
dracut:/# _

1.3 手动尝试挂载根分区的报错

dracut:/# mount /dev/centos_hp-r620/root /sysroot
mount: /dev/mapper/centos_hp--r620-root: can't read superblock

二、硬件与原始架构

2.1 硬件配置

设备 容量 类型 分区 拆分前用途 拆分后
sda (232GB) 232.4G SSD sda1(1G boot) + sda2(231G PV) centos_hp-r620 VG + root LV 部分 extent 移到 vg_ssd,建 3×50G etcd LV
sdb (1.8TB) 1.86TB 2×HDD RAID 0 sdb1(整块) centos_hp-r620 VG + 大部分 root LV 仍在 centos_hp-r620,但 PV 元数据被改
sdc (7.5G) 小容量 - sdc1/sdc2 其他用途 其他用途

2.2 LVM 架构说明(拆分前)

┌──────────────────────────────── centos_hp-r620 VG ────────────────────────────────┐
│                                                                                    │
│   sda2 (SSD, 231G PV)          sdb1 (RAID 0, 1.86T PV)                            │
│   ├─ root LV 约 30GB             ├─ root LV 约 1.78TB                               │
│   └─ (剩余空闲)                └─ swap LV(在拆分前/过程中丢失)                   │
│                                                                                    │
│              root LV(XFS 文件系统,内部记录大小 ≈ 2.06TB,跨 sda2 + sdb1)          │
└────────────────────────────────────────────────────────────────────────────────────┘

三、根因分析(按问题链)

❌ 问题 1:swap LV 丢失(启动告警源头)

现象: /dev/centos_hp-r620/swap does not exist

原因: 拆分 LVM 过程中,swap 对应的逻辑卷被删除或包含 swap 的 PV 被移出 VG,/etc/fstab 仍引用该 swap。swap 本身是非致命错误(注释掉即可),但它让 dracut 多了一层 warning。

❌ 问题 2:root LV 只剩 186GB(致命!)

现象: pvs 显示 sdb1 PSIZE 只有 <1.82t,can't read superblock

原因: 拆分时把 sda2(SSD)从 centos_hp-r620 VG 移到了 vg_ssd,导致: - VG 总空间从 2.09T 骤降到 1.86T - 但 root LV 中的 XFS 文件系统内部记录的大小仍是 2.06TB(XFS 超级块中存了文件系统总块数) - LVM 层把 root LV 映射到 1.86T,当 XFS 尝试读取文件系统末尾的 AG(Allocation Group)超级块时,设备到尽头了 - dmesg 佐证: attempt to access beyond end of device loop3: rw=32, want=4324171776, limit=3904892928 XFS (loop3): last sector read failed - want=4,324,171,776 扇区 ≈ 2.06TB(XFS 想读的位置) - limit=3,904,892,928 扇区 ≈ 1.86TB(设备实际大小) - 差值 ≈ 200GB → 正好是 sda2 的空间

❌ 问题 3:LVM PV 元数据大小错乱

现象: 早期 pvs 显示 sdb1 只有 186GB(实际磁盘 1.86TB),而 xfs_repair 扫描 2 小时找不到超级块。

原因: 拆分时在 LVM 层错误修改了 pe_count(PV 可用 extent 数),导致 sdb1 的 LVM 元数据被写坏。实际数据在磁盘上完全完好(通过 strings /dev/sdb1 | grep "XFSB\|centos\|etc" 确认能读出完整 XFS 系统结构字符串)。

❌ 问题 4:initramfs 中 LVM 状态陈旧(chroot 重建时踩坑)

现象: 即使在 Rescue 模式扩展了 root LV(2.04T,能成功挂载到 /mnt),重启后还是进 dracut。

原因: 在 Rescue 模式下 chroot /mnt 重建 initramfs 时,/mnt/etc/lvm/backup/ 和 /mnt/etc/lvm/archive/ 还是拆分前/拆分中旧版本的元数据(sda2 属于 vg_ssd 时的备份),而不是 Rescue 中刚执行 vgextend + lvextend 后的最新状态。结果 initramfs 里的 LVM 激活脚本读到错误的布局,root LV 又被映射回 1.82T。

❌ 问题 5:GRUB 模式不匹配(Legacy vs EFI)

现象: 重启后 GRUB 报错:

error: can't find command `linuxefi'.
error: can't find command `initrdefi'.

原因: Rescue 模式下 grub2-mkconfig 检测到环境中有 EFI 相关组件,生成的 grub.cfg 用了 EFI 专用命令 linuxefi / initrdefi。但服务器磁盘上实际安装的 GRUB bootloader 是 Legacy BIOS(MBR)模式,不支持这两个命令。


四、完整处理流程(按阶段分)

阶段 1:dracut 紧急模式 — 初步排查

失败原因:dracut 是极简 initramfs,缺少大量工具(od/xfs_repair/python/dd/lsblk),且文件系统为只读挂载,无法执行 vgcfgrestore 等写操作。

命令 作用与原理 结果
lvs / pvs 查看逻辑卷/物理卷当前状态,确认 swap 丢失,PV 空间异常 ❌ 发现异常大小
vgcfgrestore centos_hp-r620 -f <file> 从 LVM 备份文件恢复 VG 元数据(需先 vgchange -an) ❌ dracut 只读锁模式,write lock prohibited
mount /dev/centos_hp-r620/root /sysroot 挂载根分区 ❌ can't read superblock
strings /dev/sdb1 \| grep "XFSB\|centos" 在原始块设备上搜索可打印字符串,确认 XFS 和系统目录是否存在 ✅ 关键证据!数据完好!
grep -oba "XFSB" /dev/sdb1 查找 XFS 超级块魔数在 sdb1 上的确切字节偏移 ✅ 找到 1048576:XFSB = 偏移 1MB = LVM pe_start

阶段 2:Rescue 模式(U盘引导)— 定位缺口

用 CentOS 7 完整安装盘进入 Rescue 模式(sh-4.2#),拥有完整工具和读写权限。

命令 作用与原理 结果
lsblk / fdisk -l 查看完整磁盘布局,确认 sda(232G) sdb(1.86T) sdc(7.5G),RAID 0 表现为整块 sdb ✅ 物理盘齐全
cat /etc/lvm/archive/centos_hp-r620_*.vg \| grep -A 50 physical_volumes 查看 LVM 存档中拆分前的 PV 列表和 pe_count,确认原本就只有 sdb1 一个 PV(root LV 横跨 sdb1,但 sda2 上的 root extent 是后来扩展加上的) ✅ 存档正确,pe_count 476671 = 1.8TB
cat /sys/block/sdb/sdb1/size 读取 sdb1 真实扇区数(3904894976 ≈ 1.86TB) ✅ 真实大小正确
xfs_repair -n /dev/sdb1 在原始 sdb1 设备上检查 XFS(dry-run) ❌ 跑了 2 小时,最后 could not find valid secondary superblock,因为扫描起点没跳过 LVM 元数据 1MB 头部
losetup --offset 1048576 -f /dev/sdb1 + mount -o ro /dev/loop3 /mnt 创建 loop 设备跳过 LVM 的 1MB 元数据头部,直接从 XFS 起始处挂载 ❌ 仍然 can't read superblock。后看 dmesg 发现关键:XFS 想要 2.06TB 空间但 loop 只有 1.86TB → 空间缺口在 sda2 上!

阶段 3:LVM 修复 — 把 sda2 还回 root LV(核心修复)

优先级:root 上的 1.4~1.5T 数据 > vg_ssd 上的 etcd。先牺牲 etcd 恢复系统。

# --- 命令 1:取消激活 vg_ssd ---
vgchange -an vg_ssd
# 作用:把 vg_ssd 下所有 LV 设为 inactive,释放对 sda2 的占用
# 原理:LVM 中 PV 被 LV 占用时不能被移出 VG
# --- 命令 2:强制擦除 sda2 上的 vg_ssd PV 标签 ---
pvremove -ff /dev/sda2
# 作用:强制(-ff = force force)抹除 /dev/sda2 上属于 vg_ssd 的 LVM PV 元数据标签
# 原理:vgreduce 失败时(PV 仍被 LV extents 引用),直接擦除标签让它变成裸 PV
# 风险:vg_ssd 的 3 个 etcd LV 数据被丢弃(可后续重建)
# --- 命令 3:用旧存档恢复 centos_hp-r620 VG(可选,确保 UUID 一致) ---
vgcfgrestore centos_hp-r620 -f /etc/lvm/archive/centos_hp-r620_00000-1214265811.vg
vgchange -ay centos_hp-r620
# 作用:用拆分前最旧的 LVM 存档恢复 VG 元数据结构,确保 UUID/名字匹配
# 原理:/etc/lvm/archive 在每次 vgchange/pvcreate/lvcreate 前自动保存
# 结果:root LV 恢复到 1.82T,但文件系统要 2.06TB,还不够
# --- 命令 4:把 sda2 加回 centos_hp-r620 VG ---
pvcreate /dev/sda2
vgextend centos_hp-r620 /dev/sda2
pvs
# 作用:先把 sda2 重建成 LVM PV,再加入到 centos_hp-r620 卷组
# 原理:vgextend 把新 PV 的空闲 extents 纳入 VG 的全局可用池
# 结果:VG 总空间 = 1.86T(sdb1) + 231G(sda2) = 2.09T,满足 XFS 对 2.06T 的需求
# --- 命令 5:扩展 root LV,吞掉 sda2 上的全部空闲 extent ---
lvextend centos_hp-r620/root /dev/sda2 -l +100%FREE
lvs
# 作用:把 /dev/sda2 上所有空闲 extents 追加到 root LV 的线性映射末尾
# 原理:-l +100%FREE 表示"在指定 PV 上拿 100% 空闲空间加给 LV"
# 结果:root LV 从 1.82T → 2.04T,LVM 线性映射末尾正好补上 XFS 需要的那 200GB 尾部空间
# --- 命令 6:对扩展后的 root LV 跑 xfs_repair 修复元数据 ---
xfs_repair /dev/centos_hp-r620/root
# 作用:扫描 XFS 文件系统,修复损坏的 AG 超级块、inode B+Tree、空闲空间 B+Tree
# 原理:现在 LV 大小匹配了 XFS 内部记录的 2.06TB 大小,xfs_repair 能找到所有 AG 的备份超级块
# 结果:Phase 1-7 跑完,XFS 元数据修复完成
# --- 命令 7:挂载验证 ---
mount /dev/centos_hp-r620/root /mnt
ls -la /mnt/     # 能看到 etc/ var/ usr/ root/ home/ opt/ → ✅ 数据完整!
du -sh /mnt/*    # 总占用约 1.4~1.5T,与用户描述一致

阶段 4:chroot 重建 initramfs + GRUB

initramfs = 启动时的最小根文件系统,负责加载 LVM 模块、激活 VG、挂载真实 root 并 switch_root。旧 initramfs 中 LVM 配置是错的,必须重建。

# --- 前置:挂载必要的文件系统 ---
mount /dev/sda1 /mnt/boot          # 关键!!真实的 boot 分区(sda1)必须挂 /mnt/boot
for dir in dev dev/pts proc sys run; do
    mount --bind /$dir /mnt/$dir   # bind mount 把 Rescue 的 /sys /proc /dev 映射进 chroot
done
chroot /mnt                       # 进入真实系统环境
错误做法 ❌ 正确做法 ✅ 原因
mount --bind /boot /mnt/boot mount /dev/sda1 /mnt/boot bind 会把 Rescue 自己的 squashfs boot 软链接带进来,initramfs 会指向 Rescue 的内核
# --- 在 chroot 中执行 ---

# 1. 修正 fstab:注释掉已失效的 swap 行
sed -i 's|^/dev/mapper/centos_hp--r620-swap|#/dev/mapper/centos_hp--r620-swap|' /etc/fstab
sed -i 's|^/swapfile|#/swapfile|' /etc/fstab
# 作用:避免 dracut 因找不到 swap LV 报 warning
# 原理:fstab 中 swap 行若指向不存在设备会拖慢启动并进入 emergency shell
# 2. 重建所有内核版本的 initramfs(注意版本号不能用 Rescue 的 uname -r)
for KVER in 3.10.0-1160.119.1.el7.x86_64 \
            3.10.0-1160.45.1.el7.x86_64 \
            3.10.0-1160.36.2.el7.x86_64 \
            3.10.0-1160.el7.x86_64 \
            3.10.0-957.el7.x86_64; do
    depmod -a $KVER          # 生成 /lib/modules/$KVER/modules.dep 依赖树
    mkinitrd -f /boot/initramfs-$KVER.img $KVER
done
# 作用:用真实系统的 /etc/lvm/backup(此时仍是旧状态,见下文踩坑)+ 当前模块重建 initramfs
# 原理:mkinitrd/dracut 会把 lvm 工具、XFS 模块、/etc/lvm 元数据打包进 initrd
# 踩坑说明:此处生成的 initramfs 仍含旧 LVM 状态,因为 vgextend/lvextend 是在 Rescue 模式(非 chroot)执行的,写入的是 Rescue 的 /etc/lvm 而非 /mnt/etc/lvm。下次启动会再次进 dracut!
# 3. 重建 grub.cfg 并安装 bootloader
grub2-mkconfig -o /boot/grub2/grub.cfg
# 作用:扫描 /boot 下所有 vmlinuz + initramfs,生成 GRUB 菜单
# 踩坑说明:Rescue 环境可能让 grub2-mkconfig 误以为是 EFI 模式,生成 linuxefi/initrdefi 命令

阶段 5:首次重启 — 手动绕开 GRUB 模式错误

报错:

error: can't find command `linuxefi'.
error: can't find command `initrdefi'.

原因: 磁盘上的 GRUB bootloader 是 Legacy BIOS(MBR)模式,不识别 EFI 专用命令。

修复(临时,按 e 进入编辑):

修改前 修改后 说明
linuxefi /vmlinuz-... linux /vmlinuz-... 删除 efi 后缀,使用 Legacy 命令加载内核
initrdefi /initramfs-... initrd /initramfs-... 删除 efi 后缀,使用 Legacy 命令加载 initrd

按 Ctrl + X 启动(不是 Enter)。


阶段 6:再次进入 dracut — 手动继续启动

原因: initramfs 里的 LVM 备份是旧状态(sda2 还在 vg_ssd),激活后 root LV 又回到 1.82T 导致 XFS 挂载失败。

手动修复步骤:

# 1. 重新扫描所有 PV,找到并激活 sda2 + sdb1
/sbin/lvm pvscan --cache
/sbin/lvm vgscan --mknodes
/sbin/lvm vgchange -ay centos_hp-r620
/sbin/lvm lvs    # 确认 root 显示 2.04T(不是 1.82T)
# 2. 挂载真实 root
mount -t xfs /dev/centos_hp-r620/root /sysroot
ls /sysroot/etc    # 确认文件系统正常
# 3. 继续启动(switch_root 把 /sysroot 变成真正的 / 并运行 /sbin/init)
exec switch_root /sysroot /sbin/init
# 或 dracut 中直接:
exit

原理: dracut 紧急 shell 中的 exit 会触发 dracut 的继续启动流程,如果 /sysroot 已成功挂载就会执行 switch_root,之后 systemd 接管,服务器正常登录。


五、进入系统后的永久修复(最终闭环)

登录 CentOS 7 后,以 root 执行以下命令,一次性修复所有遗留问题:

# =========================================
# 1. 修正 grub.cfg:把 EFI 命令改回 Legacy 命令
# =========================================
sed -i 's/linuxefi/linux/g' /boot/grub2/grub.cfg
sed -i 's/initrdefi/initrd/g' /boot/grub2/grub.cfg
# 验证:应该只能搜到 "linux " 和 "initrd "(不带 efi)
grep -cE "^\s*linux " /boot/grub2/grub.cfg
grep -cE "^\s*linuxefi " /boot/grub2/grub.cfg   # 必须为 0
# =========================================
# 2. 以 Legacy 模式重新安装 GRUB bootloader 到 MBR
# =========================================
grub2-install --target=i386-pc /dev/sda
# 作用:把 i386-pc(Legacy BIOS)版本的 GRUB stage1.5+stage2 写到 /dev/sda 的 MBR + 后续扇区
# 原理:之前失败的 grub2-install 默认找 x86_64-efi 模块,但服务器是 Legacy 启动
# 结果:输出 "Installation finished. No error reported."
# =========================================
# 3. 用当前真实系统的 LVM 状态重建 initramfs(最重要的一步)
# =========================================
# 3.1 先确认当前 LVM 状态已经正确写入到真实系统的 /etc/lvm/backup
vgcfgbackup centos_hp-r620
cat /etc/lvm/backup/centos_hp-r620 | grep -E "physical_volumes|pv0|pv1|sda2|sdb1"
# 应该能看到两个 PV:sda2 和 sdb1 都在 centos_hp-r620 下

# 3.2 重建当前运行内核的 initramfs(含正确 LVM 元数据)
dracut -f /boot/initramfs-$(uname -r).img $(uname -r)
# 作用:把当前系统中 /etc/lvm/backup/centos_hp-r620 + depmod 生成的正确 modules.dep 一起打进 initramfs
# 原理:dracut 会读取 90lvm.rules + /etc/lvm 生成激活脚本
# 结果:下次启动 dracut 能正确识别 sda2+sdb1 都在 centos_hp-r620,并激活 2.04T root LV
# =========================================
# 4.(可选)为其余内核版本也重建 initramfs
# =========================================
for img in /boot/initramfs-*.img; do
    basename_img=$(basename "$img" .img)
    kver="${basename_img#initramfs-}"
    [[ "$kver" == *rescue* ]] && continue
    echo "=== 重建 $kver ==="
    dracut -f "/boot/initramfs-${kver}.img" "$kver"
done
# =========================================
# 5.(可选)重建 swap:创建 swapfile(比改 LVM 简单)
# =========================================
fallocate -l 8G /swapfile        # 8GB,按内存调整
chmod 600 /swapfile              # 安全:只有 root 可读
mkswap /swapfile                 # 格式化 swap 签名
swapon /swapfile                 # 立即启用
echo "/swapfile none swap sw 0 0" >> /etc/fstab
free -h                          # 验证 Swap: 行不再是 0
# =========================================
# 6. 最终验证 + 重启
# =========================================
df -h                           # / 挂载为 centos_hp-r620/root,/boot 挂载为 sda1
lvs                             # root 2.04t ✓ 且 a 属性 active
pvs                             # sda2 + sdb1 都在 centos_hp-r620 ✓

# 最后重启,验证是否一次成功进系统
reboot

六、命令速查表

类别 命令 作用
LVM 信息 pvs / vgs / lvs 查看 PV/VG/LV 当前状态
LVM 备份 /etc/lvm/backup/<vg> / /etc/lvm/archive/<vg>_*.vg LVM 每次变更自动生成的 VG 元数据备份
LVM 恢复 vgcfgrestore <vg> -f <备份文件> 从指定备份恢复 VG 元数据结构
LVM 空间 vgextend <vg> <pv> / lvextend <lv> <pv> -l +100%FREE 把 PV 加入 VG / 把 PV 空闲 extents 追加到 LV
XFS 修复 xfs_repair [-n] <device> XFS 文件系统检查与修复,-n 仅检查不写入
XFS 签名搜索 grep -oba "XFSB" <raw_dev> 在裸设备中定位 XFS 超级块魔数字节偏移
设备映射偏移 losetup --offset BYTES -f <dev> 创建 loop 设备跳过指定字节数(用于跳过 LVM 1MB 元数据头部)
chroot 必备 mount --bind /dev /mnt/dev 等 把 Rescue 的伪文件系统绑到待修复系统
initramfs dracut -f <img> <kver> / mkinitrd -f <img> <kver> 重建启动 initramfs 镜像
GRUB Legacy grub2-install --target=i386-pc /dev/sda Legacy BIOS 模式安装 GRUB 到磁盘 MBR
GRUB 配置 grub2-mkconfig -o /boot/grub2/grub.cfg 扫描 /boot 生成 GRUB 菜单配置
dracut 急救 pvscan; vgchange -ay; mount ... /sysroot; exec switch_root /sysroot /sbin/init 在紧急 shell 手动继续启动

七、经验总结与预防

  1. LVM 备份是救命稻草:/etc/lvm/archive/ 和 /etc/lvm/backup/ 每次 LVM 操作自动保存,拆 VG 前一定要先拷贝一份到外接存储。

  2. 拆 LV 前先看 extents 分布:执行 pvs -o +pv_used 和 lvs -o +devices,确认哪些 LV 的 extents 分布在要移除的 PV 上。必须先 pvmove /dev/<old_pv> 把数据迁走,再 vgreduce。

  3. initramfs 重建时机:在真实系统运行时重建(dracut -f),而不是 Rescue chroot。否则 chroot 内的 /etc/lvm/backup 是旧的,initramfs 会携带错误元数据再次启动失败。

  4. GRUB 模式一致性:Legacy BIOS 服务器用 --target=i386-pc,UEFI 服务器用 --target=x86_64-efi --efi-directory=/boot/efi,两者不能混用。可以用 [ -d /sys/firmware/efi ] 判断当前启动模式。

  5. 拆分 LVM 的正确顺序: ① 备份 VG 元数据到外部 → ② pvmove 把要移除 PV 上的 extents 全迁走 → ③ vgreduce 拿 PV 出 VG → ④ pvremove 清除旧标签 → ⑤ 加入新 VG → ⑥ 更新 fstab / grub2 / initramfs → ⑦ 重启验证

  6. XFS 文件系统大小 = mkfs.xfs 时设备大小:LVM 收缩 LV 会导致 XFS 尾部损坏,收缩必须先 xfs_growfs 反向缩容(不支持),只能先备份数据、重建 LV、恢复数据。本案例因 XFS 大小比 LVM 大而通过 扩大 LV 的方式反向匹配成功。


来源:/home/rain/Documents/trae_for_om/disk_ssd_partition_fix/磁盘拆分ssd问题解决.md | 最后更新:2026-08-25 04:52(由 build/sync.py 同步,请勿在站点侧修改)