服务器启动失败如何修复?Linux启动日志与引导故障排查

重启之后机器没起来——这大概是运维压力最大的场景之一:没有 SSH、没有监控、只能通过云控制台的 VNC 或串口看几行滚动的报错。慌乱之下重装系统往往是最坏的选择,因为绝大多数启动失败都能在几十分钟内定位并修复,而且数据几乎不会丢。关键在于建立一个清晰的阶段模型:机器到底卡在哪一步?本文按 固件 → GRUB → 内核/initramfs → 挂载文件系统 → systemd 服务五个阶段给出排查路径、关键日志与修复命令。

一、先建立启动阶段模型

阶段做什么典型失败现象修复入口
1. 固件(BIOS/UEFI)硬件自检、选择启动设备黑屏、No bootable device、直接进入 EFI Shell调整启动顺序、检查磁盘与 EFI 分区
2. GRUB(引导加载器)加载菜单、定位内核与 initramfserror: 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 / UbuntuRHEL 系
重建 initramfsupdate-initramfs -u -k alldracut -f --regenerate-all
重建引导菜单update-grubgrub2-mkconfig -o /boot/grub2/grub.cfg(BIOS);UEFI 环境为 grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg
安装引导记录grub-install /dev/sdagrub2-install /dev/sda
SSH 服务单元名sshsshd

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/。

六、一份可复制的修复流程

  1. 截图/保存串口输出,确认屏幕上的最后一条有效信息,据此判断卡在哪个阶段。
  2. 若能看到 GRUB 菜单:先尝试"高级选项"里的旧内核,这是成本最低的恢复路径。
  3. 进入 GRUB 编辑(按 e):把 quiet splash 之类的参数删掉,让详细输出可见;必要时追加 systemd.unit=rescue.target。
  4. 若停在 grub rescue>:用 ls 找分区,set root/prefix → insmod normal → normal 尝试进入。
  5. 若内核 panic 或掉进 initramfs shell:cat /proc/cmdline 核对 root=,blkid 核对设备,必要时 vgchange -ay。
  6. 若进入 emergency mode:journalctl -xb 定位失败挂载点,mount -o remount,rw / 后修正 /etc/fstab。
  7. 无法进入系统时:挂载云厂商救援镜像或用 ISO 启动,按第二节做 chroot,执行 update-initramfs -u -k all + update-grub + grub-install。
  8. 恢复后立即做根因复盘:是磁盘问题、配置问题还是升级问题,并补上监控与快照策略。

小结

启动失败看起来吓人,但它有一个很大的优势:故障点必然是刚发生变更的地方——新内核、新 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 记进运维手册——它们分别回答"哪里失败了"和"哪里太慢了"。

能不重装就不重装。重装解决的是"系统坏了",而启动故障通常只是"某个环节错了",后者修复成本要低一个数量级。