引导流程与 GRUB
“开机失败”不是一个单一故障:固件找不到启动项、GRUB 找不到配置、initramfs 找不到根文件系统、systemd 服务失败,都可能让屏幕停在黑底文字上。先判断接力棒掉在哪一段,比盲目重装引导器更重要。
- 适合你:已理解 BIOS/UEFI 基础,想看懂启动日志或在受控环境调整 GRUB 的读者。
- 读完能做到:描述两类固件路径以及 GRUB → 内核 → initramfs → 真实根文件系统 → init 系统的交接;收集只读证据;在虚拟机中完成一次可回滚的 GRUB 超时修改。
- 前置与安全条件:会使用终端;实操必须是可丢弃虚拟机,并先创建快照、确认能从安装/救援 ISO 启动。物理机只做观察。
- 适用范围:截至 2026-07,聚焦使用 GRUB 2 和 systemd 的常见 x86-64 Debian/Ubuntu、Arch、Fedora/RHEL 系统。systemd-boot、直接 EFI Stub、OpenRC 等只说明边界。
- 预计用时:阅读 20 分钟;虚拟机练习 25–40 分钟。
- 完成证据:一份启动链观察记录,以及“修改前配置、生成后配置检查、重启结果、回滚结果”四项证据。
1. 从电源键到登录界面的接力
1.1 固件找到第一段加载器
- Legacy BIOS 路径:固件执行选定磁盘启动区域中的代码;GRUB 的早期代码再定位
/boot/grub或/boot/grub2中的模块与配置。 - UEFI 路径:UEFI Boot Manager 根据 NVRAM 的
BootOrder/Boot####,或标准回退路径,从 ESP 加载 GRUB、shim 或其他 EFI 镜像。
所以 GRUB 并不是所有 Linux 的必经之路。systemd-boot、其他 UEFI boot manager,以及带 EFI Stub 的内核/Unified Kernel Image 都可能绕过 GRUB。本篇只处理已确认使用 GRUB的系统。
1.2 GRUB 选择内核与启动参数
GRUB 读取生成的 grub.cfg,显示菜单,并把选中的 Linux 内核、initramfs 以及内核命令行加载到内存。root=...、quiet 等参数由此交给内核;引导器不会替内核启动网络或桌面。
1.3 内核与 initramfs 找到真实根
内核初始化 CPU、内存和可用驱动,然后解包 initramfs。initramfs 是早期用户空间,常负责加载存储/文件系统驱动、组装 RAID/LVM、解锁加密卷,并挂载真正的根文件系统。
找到真实根后,早期用户空间通过 switch_root 或等价机制切换根目录,并执行真实系统中的 init。若这一步失败,常见结果是 initramfs emergency shell,而不是 GRUB 菜单。
1.4 init 系统拉起用户空间
在本文范围内,真实根上的 /sbin/init 最终启动 systemd(PID 1)。systemd 根据默认 target 及依赖关系启动挂载、设备、网络、登录终端和显示管理器。graphical.target 不等于“所有服务都成功”;应单独检查失败单元。
固件 → GRUB/shim → 内核 + initramfs → 真实根文件系统 → systemd target → 登录2. 修改之前,先确认自己在哪一段
以下命令都只读;某条不存在时记录结果,不要为了“让输出一致”安装或重装引导器。
2.1 固件、分区与引导文件
test -d /sys/firmware/efi && echo UEFI || echo Legacy-or-non-UEFI
findmnt --mountpoint /boot 2>/dev/null
findmnt --mountpoint /boot/efi 2>/dev/null
findmnt --mountpoint /efi 2>/dev/null
lsblk -o NAME,PATH,FSTYPE,PTTYPE,PARTTYPENAME,MOUNTPOINTS
sudo efibootmgr -v 2>/dev/null接着检查常见配置位置:
ls -l /etc/default/grub 2>/dev/null
ls -l /boot/grub/grub.cfg /boot/grub2/grub.cfg 2>/dev/null
ls -l /boot/loader/loader.conf 2>/dev/null
grub-install --version 2>/dev/null || grub2-install --version 2>/dev/null看到 /boot/loader/loader.conf 并不能单独证明当前由 systemd-boot 启动;要结合 UEFI 启动项和实际文件判断。若没有 GRUB 工具或配置,停止本篇的修改步骤。
2.2 当前内核参数与启动结果
cat /proc/cmdline
readlink -f /sbin/init
ps -p 1 -o pid,comm,args
systemctl get-default 2>/dev/null
systemctl --failed --no-pager 2>/dev/null
systemd-analyze time 2>/dev/null/proc/cmdline 是本次启动实际收到的参数。systemctl --failed 为空说明当前没有处于 failed 状态的单元,但不能证明所有硬件与应用都正常。
3. 认识 GRUB 配置的三层
| 层次 | 常见位置 | 应怎样对待 |
|---|---|---|
| 用户默认值 | /etc/default/grub | 常见发行版用于超时和默认内核参数;它是 shell 风格输入,必须保持语法有效 |
| 生成脚本/自定义项 | /etc/grub.d/ | 由发行版包与管理员共同维护;不要随意改动不理解的脚本 |
| 生成结果 | /boot/grub/grub.cfg 或 /boot/grub2/grub.cfg | 通常由 grub-mkconfig/grub2-mkconfig 生成;直接修改很容易在下一次生成时丢失 |
GNU GRUB 允许手写完整 grub.cfg,所以“绝对禁止”在技术上并不准确;但使用发行版自动生成流程时,应该修改源配置并重新生成,而不是把生成文件当作长期配置入口。
启动参数也不是通用优化开关。以 quiet 为例,它主要减少控制台消息,移除后便于观察日志,通常不改变驱动能力。硬件规避参数(例如关闭 PCIe AER)或显卡参数会改变内核行为,必须按具体内核、驱动和硬件文档单次测试,本篇不提供无边界推荐。
4. 安全实操:在虚拟机把菜单超时改为 3 秒
本节会改写 /etc/default/grub 并重新生成启动配置。只有同时满足以下条件才继续:目标是可丢弃虚拟机;快照已创建;救援 ISO 已连接并验证可启动;探测确认系统确实使用 GRUB。物理机、远程唯一节点或磁盘状态异常时只阅读,不执行。
4.1 记录目标与备份
先查看当前值并创建带时间戳的备份目录:
grep -E '^(GRUB_TIMEOUT|GRUB_TIMEOUT_STYLE)=' /etc/default/grub
backup_dir="$HOME/grub-backup-$(date +%Y%m%d-%H%M%S)"
mkdir -m 700 "$backup_dir"
sudo cp --preserve=all /etc/default/grub "$backup_dir/default-grub"
printf '备份目录:%s\n' "$backup_dir"把打印出的绝对路径保存到练习记录中。随后按发行版备份当前生成配置:
Debian / Ubuntu
sudo cp --preserve=all /boot/grub/grub.cfg "$backup_dir/grub.cfg"Arch Linux
sudo cp --preserve=all /boot/grub/grub.cfg "$backup_dir/grub.cfg"Fedora / RHEL
config="$(readlink -e /etc/grub2-efi.cfg 2>/dev/null || readlink -e /etc/grub2.cfg 2>/dev/null)"
test -n "$config" && printf '生成配置:%s\n' "$config"
sudo cp --preserve=all "$config" "$backup_dir/grub.cfg"Fedora/RHEL 分支用发行版提供的符号链接发现真实输出位置,避免猜测 BIOS/UEFI 路径。若 config 为空,停止操作。
4.2 修改并先做语法检查
sudoedit /etc/default/grub
sudo sh -n /etc/default/grub在编辑器中设置:
GRUB_TIMEOUT_STYLE=menu
GRUB_TIMEOUT=3sh -n 无输出且退出码为 0,表示 shell 语法可解析;它不验证每个 GRUB 变量是否有意义。如果命令报错,立即退出本节并恢复备份,不要生成配置。
4.3 按发行版重新生成
Debian / Ubuntu
sudo update-grub
sudo grub-script-check /boot/grub/grub.cfg
grep -nE 'timeout|timeout_style' /boot/grub/grub.cfg | headArch Linux
sudo grub-mkconfig -o /boot/grub/grub.cfg
sudo grub-script-check /boot/grub/grub.cfg
grep -nE 'timeout|timeout_style' /boot/grub/grub.cfg | headFedora / RHEL
config="$(readlink -e /etc/grub2-efi.cfg 2>/dev/null || readlink -e /etc/grub2.cfg 2>/dev/null)"
sudo grub2-mkconfig -o "$config"
sudo grub2-script-check "$config"
grep -nE 'timeout|timeout_style' "$config" | head生成命令应正常结束,脚本检查不应报告语法错误。grep 只帮助定位生成逻辑,不保证固件一定能加载文件。不要在检查失败时重启。
4.4 重启验证与回滚
先保持救援 ISO 已连接,再重启虚拟机。成功证据是 GRUB 菜单出现约 3 秒,系统正常进入,且 systemctl --failed 没有新增与本次操作相关的失败。
无论修改成功与否,都要练习回滚。把下面的占位路径换成第 4.1 节记录的真实备份目录:
backup_dir="<已记录的备份目录>"
sudo cp --preserve=all "$backup_dir/default-grub" /etc/default/grub然后重新执行本发行版第 4.3 节的生成与检查命令。若系统已经无法启动,不要继续向磁盘试写命令;从救援 ISO 启动并转到 Live USB Chroot 救援。
5. 故障发生时先分层
| 症状 | 更可能掉棒的位置 | 只读诊断 | 下一步决策 |
|---|---|---|---|
| 固件菜单里没有 Linux/直接提示无启动设备 | UEFI NVRAM、ESP 或 BIOS 启动区域 | Live 环境中用 lsblk、findmnt、efibootmgr -v 收集信息 | 保留 ESP 与分区表,进入第 9 章救援流程;不要先重装全部系统 |
出现 grub> 或 grub rescue> | GRUB 找不到模块、prefix 或配置 | 仅运行 set、ls、echo $prefix 记录现状 | 不使用网上硬编码的 (hd0,gpt1);从救援介质按真实 UUID/挂载关系修复 |
| GRUB 菜单正常,随后掉进 initramfs shell | 内核参数、根设备、存储/加密/文件系统驱动 | 记录屏幕错误;在 shell 中只读查看 /proc/cmdline、blkid、dmesg | 核对 root=、UUID 与 initramfs;文件系统疑似损坏时停止写入 |
| 内核启动后进入 emergency mode | fstab、必须挂载项或 systemd 单元 | systemctl --failed、journalctl -xb、findmnt --verify | 先修正明确报错的配置;不要把所有服务同时禁用 |
| 能到 TTY,图形登录不出现 | 显示管理器、图形栈或目标单元 | systemctl get-default、systemctl --failed、journalctl -b -p warning | 这通常不是 GRUB 故障,保留可登录 TTY 再查图形服务 |
若磁盘出现 I/O error、SMART/内核报告介质故障、分区表不一致,或你无法确认根分区与 ESP,停止执行 grub-install、格式化和文件系统修复命令。先只读采集证据并备份可读数据;错误目标上的“修复”可能扩大损失。
6. 可观察练习
7. 小结与下一站
现在你可以根据屏幕停留位置,把故障归到固件/GRUB、内核/initramfs 或 systemd 用户空间,并知道生成 GRUB 配置前后分别要备份和验证什么。接下来阅读 硬盘分区艺术,补齐引导链依赖的磁盘布局模型。
官方参考
- GNU GRUB 2.14 Manual
- Linux Kernel:ramfs、rootfs 与 initramfs
- Linux Kernel:使用 initial RAM disk
- systemd:Bootup
- Debian Manpages:grub-mkconfig