重启之后机器没起来——这大概是运维压力最大的场景之一:没有 SSH、没有监控、只能通过云控制台的 VNC 或串口看几行滚动的报错。慌乱之下重装系统往往是最坏的选择,因为绝大多数启动失败都能在几十分钟内定位并修复,而且数据几乎不会丢。关键在于建立一个清晰的阶段模型:机器到底卡在哪一步?本文按 固件 → GRUB → 内核/initramfs → 挂载文件系统 → systemd 服务五个阶段给出排查路径、关键日志与修复命令。
一、先建立启动阶段模型
| 阶段 | 做什么 | 典型失败现象 | 修复入口 |
|---|---|---|---|
| 1. 固件(BIOS/UEFI) | 硬件自检、选择启动设备 | 黑屏、No bootable device、直接进入 EFI Shell | 调整启动顺序、检查磁盘与 EFI 分区 |
| 2. GRUB(引导加载器) | 加载菜单、定位内核与 initramfs | error: no such device、you need to load the kernel first、grub rescue> | rescue 命令行手工引导、救援模式重装 GRUB |
| 3. 内核 + initramfs | 初始化驱动、找到根设备 | Kernel panic - not syncing: VFS: Unable to mount root fs、ALERT! /dev/xxx does not exist、dracut shell | 检查 root= 参数与 initramfs 是否包含磁盘驱动 |
| 4. 挂载文件系统 | 按 /etc/fstab 挂载 | You are in emergency mode、Timed out waiting for device | 注释或修正 fstab 条目 |
| 5. systemd 服务 | 拉起各 target 与服务 | 服务 Failed、启动极慢、网络不通 | journalctl -xb、systemd-analyze、临时关闭问题服务 |
判断的诀窍:看屏幕上最后一条有效输出属于哪一层。能出现 GRUB 菜单就说明前两层没问题;能看到内核滚动输出就说明内核已加载;能看到 Reached target 字样就说明文件系统挂载成功了。这条分界线能把排查范围压缩到二分之一以内。
1.1 第一时间要做的两件事
- 打开串口/控制台日志并截图。云厂商控制台通常提供"实例截图"或"串口输出",这是唯一的证据来源,重启后可能被覆盖。
- 不要急着重装。只要能看到
grub rescue>、emergency mode或initramfs提示符,系统盘上的数据都还在。
二、阶段 2:GRUB 故障
典型报错与含义:
error: no such device: 3f2a...-...:GRUB 找不到它认为的/boot所在分区,通常是 UUID 变了(换盘、克隆、调整分区)。error: file '/vmlinuz-...' not found:内核文件丢失,常见于/boot分区写满导致更新中断。grub rescue>:连normal.mod都找不到,核心模块区损坏或分区表变化。- 直接进入 EFI Shell:EFI 启动项丢失或顺序错误。
2.1 在 grub rescue 里手工引导
# 列出可见设备与分区 grub rescue> ls grub rescue> ls (hd0,1)/ grub rescue> ls (hd0,2)/boot # 逐个试,找到含 vmlinuz 与 initrd 的分区后,设置前缀并加载正常模式 grub rescue> set root=(hd0,2) grub rescue> set prefix=(hd0,2)/boot/grub grub rescue> insmod normal grub rescue> normal # 若 normal 能起来,进入菜单后按 e 编辑该条目,确认根设备后启动 # 或者直接在 grub 命令行引导(注意 root= 要填实际根分区): grub> linux /boot/vmlinuz-6.8.0-31-generic root=/dev/sda2 ro grub> initrd /boot/initrd.img-6.8.0-31-generic grub> boot
这里的 root=/dev/sda2 是应急写法。一旦系统起来,应立刻改为用 UUID 表达根设备,避免磁盘顺序变化后再次失败:
blkid grep -n 'root' /proc/cmdline grep -v '^#' /etc/fstab
2.2 救援模式下重装 GRUB(最常用)
用安装介质(ISO/云厂商的救援镜像)启动,进入 shell 后 chroot 到原系统。下面以 Debian/Ubuntu 为例:
# 1. 确认原系统分区(用 lsblk -f 和 blkid 看 UUID 与文件系统) lsblk -f # 2. 挂载根分区(按你的实际布局调整;LVM 卷通常是 /dev/mapper/vg-lv) mount /dev/sda2 /mnt # 3. 若有独立的 /boot 与 EFI 分区,必须一起挂上,否则 grub-install 会失败 mount /dev/sda1 /mnt/boot # 独立的 /boot(如有) mount /dev/sda15 /mnt/boot/efi # EFI 分区(UEFI 启动时必须有) # 4. 绑定运行时目录,让 chroot 环境可用 mount --bind /dev /mnt/dev mount --bind /proc /mnt/proc mount --bind /sys /mnt/sys # UEFI 场景还需要 efivars mount -t efivarfs none /mnt/sys/firmware/efi/efivars # 5. 进入原系统 chroot /mnt # 6. Debian/Ubuntu:重建 initramfs、重建菜单、重装引导记录 update-initramfs -u -k all update-grub grub-install /dev/sda # 注意是整块磁盘,不是分区 exit umount -R /mnt reboot
RHEL / Rocky / Alma / CentOS 系列的命令对应关系:
| 目的 | Debian / Ubuntu | RHEL 系 |
|---|---|---|
| 重建 initramfs | update-initramfs -u -k all | dracut -f --regenerate-all |
| 重建引导菜单 | update-grub | grub2-mkconfig -o /boot/grub2/grub.cfg(BIOS);UEFI 环境为 grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg |
| 安装引导记录 | grub-install /dev/sda | grub2-install /dev/sda |
| SSH 服务单元名 | ssh | sshd |
2.3 UEFI 特有的坑
# 查看与重建 EFI 启动项(在救援环境或系统内执行) efibootmgr -v efibootmgr -c -d /dev/sda -p 1 -L "debian" -l '\EFI\debian\grubx64.efi' efibootmgr -o 0001,0002 # 确认 EFI 分区存在且为 FAT 格式 lsblk -f | grep -i vfat ls -l /boot/efi/EFI/
最常见的 UEFI 故障是"用 Legacy/BIOS 模式安装的系统,后来把虚拟机固件改成了 UEFI",或者反过来。表现为固件完全找不到可启动项。修复前务必确认云控制台/BIOS 里的固件模式与安装时一致,否则 grub-install 怎么装都没用。
三、阶段 3:内核 panic 与 initramfs 问题
如果屏幕停在:
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0) # 或 ALERT! UUID=xxxx does not exist. Dropping to a shell!
说明 initramfs 里缺少识别根设备所需的驱动,或者 root= 参数指向了错误设备。常见于:更换了磁盘控制器/云盘类型、LVM 或软 RAID 元数据未激活、内核升级后 initramfs 未生成。
# 在 initramfs 的应急 shell 里,先看看内核识别到了哪些磁盘 ls /dev/sd* /dev/nvme* /dev/mapper/ cat /proc/partitions blkid # 检查内核命令行里 root= 写的是什么 cat /proc/cmdline # 若是 LVM/RAID 未激活,在 initramfs 里手动激活后再退出继续启动 lvm vgchange -ay mdadm --assemble --scan
能临时启动后,必须重建 initramfs 并确认驱动模块已被包含:
lsinitramfs /boot/initrd.img-$(uname -r) | grep -iE 'nvme|virtio|megaraid|sd_mod|dm_mod' sudo update-initramfs -u -k all # 确认 /etc/initramfs-tools/modules(Debian 系)里是否需要补充驱动 grep -v '^#' /etc/initramfs-tools/modules
另一个高频原因是 /boot 分区写满:内核更新时 initramfs 只生成了一半,重启必然失败。检查与清理:
df -h /boot ls -lh /boot dpkg -l | grep -E 'linux-image|linux-headers' # Debian/Ubuntu # rpm -qa | grep kernel # RHEL 系 # 删除旧内核(务必保留至少一个能启动的版本) sudo apt autoremove --purge sudo update-grub
生产环境的铁律:永远保留至少一个可用的旧内核。内核升级后启动失败时,在 GRUB 的"高级选项"里选旧内核进入系统,是最快的恢复手段。这也是为什么不要启用激进的内核自动清理。
四、阶段 4:fstab 挂载失败与 emergency mode
见到 You are in emergency mode. After logging in, type "journalctl -xb" to view system logs,十有八九是 /etc/fstab 里某个条目挂不上。这是最"友好"的一类启动故障,因为系统已经起来了,只是没进入默认 target。
# 1. 输入 root 密码进入应急 shell 后,先看是什么没挂上 journalctl -xb --no-pager | grep -iE 'mount|failed|timed out|dependency' systemctl --failed systemctl status local-fs.target --no-pager # 2. 根分区可能只读,需要先重挂为可写 mount -o remount,rw / # 3. 查看当前挂载情况与 fstab 对比 findmnt --verify cat /etc/fstab blkid # 4. 先注释掉有问题的行(在行首加 #),重启验证 vim /etc/fstab reboot
修好之后,把 /etc/fstab 里的设备路径从 /dev/sdXN 改成 UUID 形式,并给非关键磁盘加上容错参数:
# 查看 UUID blkid /dev/sdb1 # /etc/fstab 推荐写法示例 UUID=1a2b3c4d-.... /data ext4 defaults,nofail,x-systemd.device-timeout=10 0 2
nofail 表示这块盘挂不上也不阻断启动;x-systemd.device-timeout=10 把等待时间从默认的 90 秒缩短到 10 秒,避免一块网络盘把开机拖慢几分钟。注意 nofail 与 nobootwait 的区别:后者是 Upstart 时代的写法,在 systemd 上无效。
4.1 文件系统损坏:fsck
如果日志里出现 ext4 的 EXT4-fs error、Remounting filesystem read-only,或者系统提示需要手工 fsck,处理方式如下。
# 查看是否需要检查(ext2/3/4) sudo tune2fs -l /dev/sda2 | grep -E 'Mount count|Maximum mount count|Last checked|Check interval|Filesystem state' # 必须先卸载再检查;根分区请在救援模式或 initramfs 环境中操作 umount /dev/sdb1 fsck -f -y /dev/sdb1 # 强制下次启动时检查根分区 touch /forcefsck reboot # XFS 用 xfs_repair(同样需要卸载) umount /dev/sdb1 xfs_repair /dev/sdb1
两个注意点:一、绝对不要对已挂载的文件系统执行 fsck,那会直接造成更严重的数据损坏;二、XFS 的 xfs_repair 若提示日志中有待回放的数据,应先挂载再正常卸载一次,让日志回放完成,而不是直接加 -L(清空日志),那会丢失最近的写入。
五、阶段 5:systemd 服务卡住
系统能登录但服务起不来、或者开机极慢,属于这一类。
# 本次启动的错误日志(优先级 3 及以上 = err/critical/alert/emerg) journalctl -xb -p err --no-pager # 哪些单元失败了 systemctl --failed systemctl list-units --state=failed # 开机耗时分析:谁最慢、关键路径在哪 systemd-analyze systemd-analyze blame | head -20 systemd-analyze critical-chain systemd-analyze plot > /tmp/boot.svg # 单个服务的日志 journalctl -u nginx.service -b --no-pager # 校验单元文件语法 systemd-analyze verify /etc/systemd/system/app.service
5.1 临时让机器先起来
当某个服务反复失败阻塞了整个启动流程时,先把它禁用掉,保证业务能恢复,再慢慢修:
# 临时屏蔽(比 disable 更彻底,防止被依赖拉起) systemctl mask problem.service # 或者进入 rescue.target(单用户,不启动多数服务) systemctl rescue # 在 GRUB 里也可以加内核参数:systemd.unit=rescue.target # 或最简形式:init=/bin/bash (仅用于紧急修复,网络与多数服务不可用)
如果是网络配置错误导致 SSH 连不上,而你能通过控制台进入系统,可临时回退到 DHCP 验证连通性;Debian/Ubuntu 用 netplan(/etc/netplan/*.yaml,netplan apply),RHEL 系用 NetworkManager 的 nmcli 或 /etc/sysconfig/network-scripts/。
六、一份可复制的修复流程
- 截图/保存串口输出,确认屏幕上的最后一条有效信息,据此判断卡在哪个阶段。
- 若能看到 GRUB 菜单:先尝试"高级选项"里的旧内核,这是成本最低的恢复路径。
- 进入 GRUB 编辑(按
e):把quiet splash之类的参数删掉,让详细输出可见;必要时追加systemd.unit=rescue.target。 - 若停在
grub rescue>:用ls找分区,set root/prefix→insmod normal→normal尝试进入。 - 若内核 panic 或掉进 initramfs shell:
cat /proc/cmdline核对root=,blkid核对设备,必要时vgchange -ay。 - 若进入 emergency mode:
journalctl -xb定位失败挂载点,mount -o remount,rw /后修正/etc/fstab。 - 无法进入系统时:挂载云厂商救援镜像或用 ISO 启动,按第二节做 chroot,执行
update-initramfs -u -k all+update-grub+grub-install。 - 恢复后立即做根因复盘:是磁盘问题、配置问题还是升级问题,并补上监控与快照策略。
小结
启动失败看起来吓人,但它有一个很大的优势:故障点必然是刚发生变更的地方——新内核、新 fstab 条目、新磁盘、新服务。把"最后一条屏幕输出"映射到五个阶段中的某一层,剩下的就是按图索骥。
避坑建议:
- 内核升级后至少保留一个旧内核不要清理,这是最快的回退通道。
- 定期检查
df -h /boot。/boot写满会让 initramfs 生成一半,重启时必然 panic。 /etc/fstab一律用 UUID,非关键挂载点加nofail与x-systemd.device-timeout,别让一块数据盘拖垮整个开机流程。- 不要对已挂载的文件系统执行
fsck;XFS 修复慎用-L。 - chroot 修复时别忘了挂载
/dev、/proc、/sys,UEFI 场景还要挂efivarfs和 EFI 分区,否则grub-install会报莫名其妙的错误。 - 确认固件模式(BIOS 还是 UEFI)与系统安装时一致,模式不匹配是"怎么装 GRUB 都没用"的头号原因。
- 修复前先给系统盘做快照或云盘镜像。这一步几十秒,但能让你在误操作后全身而退。
- 把
journalctl -xb和systemd-analyze blame记进运维手册——它们分别回答"哪里失败了"和"哪里太慢了"。
能不重装就不重装。重装解决的是"系统坏了",而启动故障通常只是"某个环节错了",后者修复成本要低一个数量级。
企业QQ咨询




