Linux 基础 24:启动流程与救援——UEFI、GRUB、initramfs 与 emergency mode

发布于 2022-05-02 20:30 更新于 2022-05-02 22:10 1342 字 7 min read ... 访问量 手写 每个字都是我自己敲的。

Linux 基础 25:收尾——自查清单与继续深入的方向Linux 基础 24:启动流程与救援——UEFI、GRUB、initramfs 与 emergency modeLinux 基础 23:容器与内核边界——namespace、cgroup 与 docker exec 背后Linux 基础 22:日志与故障排查方法论——从现象到根因的六步Linux 基础 21:定时任务——crontab 的坑与 systemd timerLinux 基础 20:Shell 脚本(下)——trap、日志、幂等与并发锁Linux 基础 19:Shell 脚本(上)——引号、条件与退出码Linux 基础 18:性能观测与 strace——机器到底卡在哪Linux 基础 17:防火墙——iptables、nftables、firewalld 与 ufw 的关系Linux 基础 16:SELinux——当权限都对,服务还是被拒绝Linux 基础 15:权限进阶——sudoers 的通配陷阱、ACL 与 capabilitiesLinux 基础 14:SSH 与远程运维——密钥、权限与三种隧道Linux 基础 13:网络基础——自下而上的排错顺序Linux 基础 12:磁盘与文件系统——从块设备到挂载点Linux 基础 11:systemd——unit、systemctl 与 journalctl 的正确用法Linux 基础 10:包管理——apt 到底做了什么,以及四个高频报错Linux 基础 09:用户与组——passwd、shadow、sudoers 三件套Linux 基础 08:环境变量与 shell 启动文件——为什么 ssh 跑命令找不到你的 PATHLinux 基础 07:进程与信号——TERM 和 KILL 到底差在哪Linux 基础 06:管道与重定向——三条流、一个顺序问题Linux 基础 05:文本处理——把 grep/sort/uniq 变成你的分析工具Linux 基础 04:权限与属主——rwx 在文件和目录上不是一回事Linux 基础 03:ls、cp、mv、rm 的真实语义,以及那个由 shell 展开的 *Linux 基础 02:/ 底下为什么是这些目录,inode 里到底存了什么Linux 基础 01:终端、Shell,和命令是怎么被找到的
从固件到 GRUB2 再到内核、initramfs、systemd 的完整启动链、用 systemd-analyze 观察启动、在 GRUB 里改内核参数进救援模式、root 密码重置流程,以及 fstab 写错掉进 emergency mode 的修复步骤与预防纪律。

这一节要解决什么

改完 /etc/fstab 重启,机器卡在 emergency mode,一屏红字末尾一句 Give root password for maintenance;或者单纯忘了 root 密码,需要从控制台进去重置。这时候能不能救回来,取决于你懂不懂启动链条长什么样、以及那条链上哪一环是可以手动干预的。

这一节先把启动流程走一遍,再讲三个救援入口和两个经典救援场景。

一、启动链条

通电 → UEFI/BIOS 自检 → 读启动项 → 引导器(GRUB2)
     → 载入内核 vmlinuz 加 initramfs(临时根,含驱动与解密)
     → 内核挂真正的根文件系统 → systemd (PID 1) → 目标 target
组件作用
固件 UEFI/BIOS找启动设备;ESP 分区挂在 /boot/efi,FAT32 格式
GRUB2启动菜单与内核参数;配置在 /boot/grub2/grub.cfg
initramfs迷你根文件系统,负责挂载根、LUKS 解密、加载驱动
systemd拉起服务到达 multi-user.target 或 graphical.target

关键结论:/boot 里有两样"救命"的东西——已知可用的旧内核和 GRUB 菜单。新内核起不来时,能在菜单里选旧的进去修。留着它们,比什么都重要。

二、观察启动

systemd-analyze                     # 内核加用户态总耗时
systemd-analyze blame | head        # 各服务耗时排行
systemd-analyze critical-chain      # 关键路径,哪一步拖住了主线
cat /proc/cmdline                    # 本次启动的内核参数
journalctl -b -1 -p err              # 上次开机的错误,崩溃后查这个

三、救援:在 GRUB 里改内核参数

GRUB 菜单里选中条目按 e 编辑,在 linux 那一行末尾追加:

参数用途
single 或 1进单用户,旧 SysV 语义,systemd 上约等于 rescue
rd.break在 initramfs 阶段停下一个 shell,此时还没挂真正的根
init=/bin/bash内核直接起 bash,跳过 systemd
systemd.unit=rescue.target到 rescue 目标,本地已挂载、少量服务
rw 或 ro根文件系统先挂成可写或只读

批注:rd.break 停在 initramfs 阶段,此时真正的根还挂在 /sysroot;init=/bin/bash 则已经挂了根,但没有其他服务在跑。选哪个,取决于你要修的是"挂根之前"还是"起来之后"的问题。

四、root 密码重置(RHEL 系标准流程)

# 1) GRUB 菜单按 e,在 linux 行末尾加 rd.break,然后 Ctrl-x 启动
# 2) 停在 initramfs shell 后:
mount -o remount,rw /sysroot        # 把真正的根挂成可写
chroot /sysroot                     # 切进真正的根
passwd root                         # 改密码
touch /.autorelabel                 # 让下次启动重打 SELinux 标签
exit                                # 退出 chroot
reboot

为什么必须 touch /.autorelabel:在 initramfs 里改了 /etc/shadow,SELinux 上下文会不对;不重打标签,改完密码可能反而登不进去。这一条是整套流程最容易漏的。

这套流程的前提是你能物理接触机器或进控制台(云主机走 VNC 或串口控制台)。它对任何能接触硬件的人开放,所以机房物理安全、云主机控制台权限本身就是安全边界——别把"改个密码就能进"当成理所当然。

五、fstab 写错 → emergency mode

改 /etc/fstab 手滑写了个不存在的 UUID,重启后 systemd 挂不上,掉进 emergency mode:

# 在 emergency shell(或输 root 密码进 maintenance)之后:
journalctl -xb | grep -i -E 'failed|fstab|mount' | tail -30   # 找到报错那一行
mount -o remount,rw /                                          # 根通常是只读挂进来的
vi /etc/fstab                                                  # 注释掉或修好坏行
mount -a                                                       # 先验证所有条目都能挂
systemctl default                                              # 回到默认 target 继续启动

批注:mount -a 是改完 fstab 后必须的一步——它一次性把所有条目试挂一遍,写得不对当场报错,而不是等下次重启掉进 emergency。第 12 节讲 UUID 时就强调过这条。

六、纪律

  • 改 /etc/fstab 或引导参数前,先 mount -a 或在测试机上验证。
  • 保底至少留一个已知可用的旧内核(dnf install kernel 可并存多版本,GRUB 菜单里就能选)。
  • 动引导链之前,记住三个入口:e 编辑、rd.break、init=/bin/bash——知道进哪儿,也知道怎么退。

七、动手清单

systemd-analyze; systemd-analyze blame | head         # 1. 启动耗时
systemd-analyze critical-chain | head                  # 2. 关键路径
cat /proc/cmdline                                      # 3. 当前内核参数
ls /boot/vmlinuz-* /boot/initramfs-* 2>/dev/null       # 4. 装了哪些内核
systemctl get-default                                  # 5. 默认 target
sudo findmnt --verify --verbose | head                 # 6. 校验 fstab 条目

小结

  • 启动链:固件 → GRUB2 → 内核加 initramfs → systemd → target;ESP 分区在 /boot/efi。
  • systemd-analyze(blame、critical-chain)看耗时;/proc/cmdline 看本次参数;journalctl -b -1 看上次开机。
  • 救援入口:GRUB 按 e 加 single、rd.break、init=/bin/bash 或 systemd.unit=rescue.target。
  • root 重置:rd.break → mount -o remount,rw /sysroot → chroot → passwd → touch /.autorelabel → exit。
  • fstab 写错进 emergency:journalctl -xb 找错 → remount,rw / → 修 fstab → mount -a 验证 → systemctl default。
  • 纪律:改 fstab 或引导前先验证,永远留一个已知可用的旧内核。

下一节预告

下一节是本系列收尾——四张上线前的自查清单、一张"现象到首选命令"的对照表,以及继续深入的方向与一条可以长期沿用的排障方法论。

执笔 手写

喜欢的话,留下你的评论吧~

加载中...