前言

服务器卡在启动界面进不去系统时,看懂启动流程就是看懂排障地图。这篇从固件到 shell,一步步走完 Linux 的"出生过程"。

一、总览:六个阶段

① 固件自检 (BIOS/UEFI)
      ▼
② 引导加载 (GRUB2)
      ▼
③ 内核加载 (vmlinuz + initramfs)
      ▼
④ PID 1 (systemd 启动)
      ▼
⑤ 并行拉起服务 (target + 依赖)
      ▼
⑥ 登录 (getty / sshd)

二、阶段一:固件(BIOS/UEFI)

BIOS(老)                          UEFI(现代)
按 MBR 磁盘前512字节引导              读 FAT 格式的 ESP 分区里的 .efi 文件
    │                                  │
    ▼                                  ▼
MBR: 引导代码446B + 分区表64B          /boot/efi/EFI/.../grubx64.efi
     + 魔数 55AA
# 看自己的机器是哪种
[ -d /sys/firmware/efi ] && echo UEFI || echo BIOS

# UEFI 下看启动项
efibootmgr -v

# 固件层常见故障: 启动顺序错了 / 磁盘没认出来
#    → 进 BIOS Setup 检查 Boot Order 与磁盘是否识别

三、阶段二:GRUB2 引导

GRUB 的任务:找到内核与 initramfs,把控制权交出去。

# GRUB 配置的生成链(别直接改 grub.cfg!)
/etc/default/grub            # 人类编辑的配置
    │ grub2-mkconfig
    ▼
/boot/grub2/grub.cfg         # 机器生成的最终配置

# 改内核启动参数的标准流程
vim /etc/default/grub
#   GRUB_CMDLINE_LINUX="... quiet"      ← 加参数在这
grub2-mkconfig -o /boot/grub2/grub.cfg

实战:忘记 root 密码(GRUB 是突破口):

1. 重启, 在 GRUB 菜单按 e 编辑
2. 找到 linux 行, 末尾追加:  rd.break
3. Ctrl+X 启动 → 进入紧急 shell(内存里的系统)
4. mount -o remount,rw /sysroot
   chroot /sysroot
   passwd root
   touch /.autorelabel           # SELinux 重新打标签(重要!)
   exit; exit

四、阶段三:内核与 initramfs

GRUB 加载 /boot/vmlinuz-$(uname -r)      ← 内核本体
      + /boot/initramfs-*.img            ← 内存里的迷你根文件系统

initramfs 的存在意义:根文件系统可能需要驱动才能挂载(磁盘阵列、LVM、加密盘)——鸡生蛋问题。initramfs 先在内存里起来,加载必要驱动,挂上真根后执行 switch_root 交接。

# 看看 initramfs 里有什么
lsinitrd | head -30
# 能看到内核模块、microcode、mkinitrd 脚本...

# 磁盘/驱动变更后重建
dracut -f

内核起来后最早期日志看:

dmesg | head -30              # 内核环形缓冲
journalctl -b -o short-monotonic | head -30

五、阶段四/五:systemd 时代

内核启动的第一个用户态进程 PID 1 = systemd:

ps -p 1 -o comm=          # systemd
systemd --version

并行启动是 systemd 相对 SysV init 的革命:靠声明依赖(After/Wants/Requires,详见服务管理篇)把串行等待变成并行拉起——这就是现代 Linux 十几秒开机的原因。

target = 一组服务的集合(启动里程碑):

systemctl get-default                 # 当前默认: multi-user.target 或 graphical.target
systemctl list-dependencies multi-user.target | head

# 切换运行级别(即时)
systemctl isolate multi-user.target   # 图形 → 字符界面
target 含义
multi-user.target 多用户字符界面(服务器标配)
graphical.target 图形桌面
rescue.target 单用户救援(本地有控制台)
emergency.target 紧急模式(只挂 / 只读)

六、阶段六:登录与用户会话

# 本地终端(Ctrl+Alt+F2~F6 切换)
systemctl status getty@tty2

# 远程登录
systemctl status sshd

# 登录后发生什么?
# /etc/profile → /etc/profile.d/*.sh → ~/.bash_profile → ~/.bashrc
# (顺序影响环境变量, 排查 PATH 问题时按这条链查)

七、开机慢?逐段计时

systemd-analyze                       # 总耗时
# Startup finished in 2.1s (kernel) + 4.5s (initrd) + 8.3s (userspace)

systemd-analyze blame | head          # 每个服务耗时排名
systemd-analyze critical-chain        # 关键路径(谁拖累了谁)
systemd-analyze plot > boot.svg       # 可视化时间线

优化手段:systemctl disable 不需要的服务、NetworkManager-wait-online 常是元凶。

八、启动故障排障地图

卡住位置 线索 处理
黑屏无 GRUB 固件不认盘 检查磁盘/启动项;修 MBR/ESP
GRUB 报错 grub rescue> grub.cfg 丢失/分区变 ls 找到启动分区,手动 insmod normal
卡在 Loading initramfs initramfs 损坏/缺驱动 救援盘 chroot 后 dracut -f
进入 emergency mode fsck 失败/fstab 挂载失败 看 journalctl;修 fstub(常是 UUID 写错)
卡在某个服务 systemd-analyze blame disable 或修该服务
起来了但 ssh 连不上 sshd 未起/防火墙 控制台进 systemctl status sshd

emergency/rescue 模式进入方式:

# GRUB 内核参数追加
systemd.unit=rescue.target
systemd.unit=emergency.target

# 或已能登录时
systemctl rescue

九、完整排障演练:fstab 写错进不了系统

现象: 开机进 emergency mode, 提示 "Dependency failed for /data"
原因: /etc/fstab 里挂了一块已不存在的盘
处理:
  1.emergency shell 下: journalctl -xb | grep -i mount
  2. mount -o remount,rw /
  3. vim /etc/fstab     → 注释掉那行坏盘
  4. mount -a           → 验证无报错
  5. reboot             → 顺利进入系统

这就是启动流程知识的实战价值:每一层失败都有对应入口与工具。

小结

阶段 关键组件 排障工具
固件 BIOS/UEFI + 启动项 Setup / efibootmgr
引导 GRUB2 按 e 编辑 / grub2-mkconfig
内核 vmlinuz + initramfs dmesg / dracut -f
初始化 systemd journalctl -b / systemd-analyze
登录 getty/sshd systemctl status

本文是「Linux 基础」系列第 8 篇。