1. 课程导论与初始化流程概览:理解 systemd 初始化阶段的重要性,从内核启动到 PID 1 的交接过程
1.1 为什么初始化阶段是故障排查的核心战场?
Linux 系统的启动过程可以划分为两个截然不同的阶段:内核引导与用户空间初始化。内核引导阶段相对固定,故障通常集中在硬件兼容性或驱动加载上;而用户空间初始化阶段——即 systemd 接管后的部分——则涉及数百个服务、依赖关系、资源限制和自定义配置,是生产环境中 70% 以上启动故障 的根源。
理解从内核启动到 PID 1 交接的完整链路,是定位“系统卡在启动”、“服务启动超时”、“依赖循环”等问题的前提。本章将建立这一关键认知框架。
/lib/systemd/systemd。此后的所有服务、挂载点、套接字、定时器都由它管理。初始化阶段的故障,本质上是 PID 1 与其管理的单元之间的交互失败。
1.2 从内核启动到 PID 1 交接:四阶段模型
整个启动流程可以抽象为四个连续阶段。下表总结了每个阶段的核心动作、输出产物以及常见的故障点:
| 阶段 | 核心动作 | 输出/标志 | 常见故障点 |
|---|---|---|---|
| 1. 固件/引导加载器 | BIOS/UEFI 初始化硬件 → 引导加载器(GRUB2)加载内核与 initramfs | 内核映像与 initramfs 位于内存 | 引导参数错误、initramfs 损坏、磁盘加密密码输入失败 |
| 2. 内核引导 | 解压内核 → 初始化核心子系统(内存管理、调度器、中断)→ 挂载根文件系统 | 内核日志环形缓冲区(dmesg) | 驱动缺失、根文件系统无法挂载、硬件 ACPI 错误 |
| 3. initramfs 过渡 | 运行临时根文件系统中的 /init → 加载必要驱动与模块 → 挂载真实根文件系统 → 执行 switch_root |
PID 1 从 /init 切换到 /sbin/init(指向 systemd) |
块设备无法识别、LVM/RAID 无法激活、switch_root 失败 |
| 4. systemd 初始化 | PID 1 执行 → 加载配置 → 启动默认目标单元 → 按依赖图并行启动服务 | 系统进入 multi-user.target 或 graphical.target | 服务依赖循环、单元文件语法错误、资源耗尽、超时 |
systemd.log_level=debug 和 rd.debug 来获取更详细的诊断输出。
1.3 PID 1 交接的精确时刻:switch_root 与 exec
交接过程并非瞬间完成,而是通过 switch_root 系统调用实现。initramfs 中的 /init 脚本完成以下步骤后,才会将控制权交给真正的 systemd:
- 挂载真实根文件系统到
/sysroot(例如/dev/sda2)。 - 移动当前挂载点:将
/dev、/proc、/sys等虚拟文件系统从 initramfs 移动到/sysroot下。 - 执行
switch_root:将根目录切换到/sysroot,并执行/sbin/init(即 systemd)。
从这一刻起,PID 1 的身份正式变为 systemd,它开始读取配置文件并构建初始单元依赖图。
# 典型的 initramfs /init 脚本末尾(简化)
# 挂载真实根文件系统
mount /dev/sda2 /sysroot
# 移动虚拟文件系统
mount --move /proc /sysroot/proc
mount --move /sys /sysroot/sys
mount --move /dev /sysroot/dev
# 切换到真实根并执行 systemd
exec switch_root /sysroot /sbin/init
switch_root 执行失败(例如 /sbin/init 不存在或损坏),系统会陷入 kernel panic。此时应检查 initramfs 是否包含正确的 systemd 二进制文件,以及根文件系统是否完整。
1.4 systemd 初始化阶段的核心架构
systemd 接管后,其初始化过程并非线性执行,而是基于 目标单元(target) 和 依赖关系 的并行启动模型。下图展示了从 PID 1 启动到默认目标达成的高层架构:
1.5 目标单元(Target)与运行级别的对应关系
systemd 使用 目标单元(.target) 替代传统的 SysV 运行级别。目标单元本身不执行任何操作,它只是将其他单元(服务、挂载点、套接字等)组织成一个同步点。下表列出了常见的目标单元及其与传统运行级别的对应关系:
| systemd 目标单元 | 传统运行级别 | 用途描述 | 典型包含的服务 |
|---|---|---|---|
poweroff.target |
0 | 关机 | 关闭所有服务 → 卸载文件系统 → 断电 |
rescue.target |
1 | 单用户救援模式 | 仅挂载根文件系统,启动 emergency.service |
multi-user.target |
3 | 多用户非图形模式 | 网络服务、SSH、cron、日志系统 |
graphical.target |
5 | 多用户图形模式 | multi-user.target + 显示管理器(GDM/SDDM) |
reboot.target |
6 | 重启 | 关闭所有服务 → 重新挂载根文件系统为只读 → 重启 |
systemd.unit=rescue.target 来进入救援模式,绕过有问题的服务。这是最常用的故障隔离手段之一。
1.6 初始化阶段的故障分类与排查思路
根据故障发生的时机和表现,可以将初始化阶段故障分为以下三类。理解分类有助于快速缩小排查范围:
- 依赖图构建失败:systemd 在启动初期解析单元文件时发现循环依赖、缺失依赖或语法错误。表现为系统在启动早期卡住,
systemctl list-jobs显示大量 pending 作业。 - 服务启动超时:某个服务在指定的
TimeoutStartSec内未能完成启动。表现为系统进入 degraded 状态,systemctl status显示该服务为 failed。 - 资源耗尽:PID 1 或关键服务因内存不足、文件描述符耗尽、磁盘 I/O 阻塞而无法继续。表现为系统响应缓慢,日志中出现
Cannot allocate memory或Too many open files。
journalctl -b -p err 查看当前启动的错误级别日志,或使用 journalctl --list-boots 查看历史启动记录。不要盲目重启或修改配置。
1.7 本章小结与课程路线图
本章建立了 systemd 初始化阶段的基础认知框架:从内核启动到 PID 1 交接的四阶段模型、systemd 初始化架构、目标单元的作用以及故障分类。后续章节将深入每个环节:
- 第 2-5 章:目标单元与依赖关系分析
- 第 6-10 章:服务单元启动机制与超时处理
- 第 11-15 章:资源限制与 cgroup 故障排查
- 第 16-20 章:套接字、定时器与路径激活
- 第 21-25 章:日志分析与调试工具实战
- 第 26-30 章:高级故障场景与性能优化
掌握本章的流程概览,是后续深入排查所有初始化阶段故障的基石。