Ubuntu 系统启动流程与服务管理机制
Ubuntu 自 15.04 起全面转向 systemd 作为 PID 1 的 init 系统(Ubuntu 16.04 LTS 是最后一个还保留部分 Upstart 痕迹的版本),到 2026 年,Ubuntu 24.04 LTS 和即将主流的 26.04 LTS 都完全建立在 systemd 之上。
systemd 不仅仅是一个启动管理器,它是一个系统与服务管理器,负责启动顺序、依赖关系、并行启动、服务监督、重启策略、日志、挂载、网络等待、设备热插拔等几乎所有用户空间初始化与运行时管理任务。
1. 现代 Linux 启动全流程(从按电源键到登录提示)
启动过程可以分为五个主要阶段,每个阶段的职责边界清晰:
| 阶段 | 执行主体 | 主要职责 | 输出形式 / 可观测点 | 典型耗时占比(SSD + 现代硬件) |
|---|---|---|---|---|
| 1 | 固件(Firmware) | POST、自检、硬件初始化、加载 UEFI 变量 | BIOS/UEFI 界面、蜂鸣声、LED 灯 | 2–10 秒 |
| 2 | 引导加载器(Bootloader) | 选择内核、加载 initramfs、传递内核参数 | GRUB 菜单(或 systemd-boot) | 1–5 秒 |
| 3 | 内核(Kernel) | 解压 initramfs、驱动初始化、挂载根文件系统 | dmesg、黑屏或内核参数 quiet 隐藏 | 3–15 秒 |
| 4 | init 用户空间(PID 1) | systemd 初始化、激活 default.target | Plymouth 启动画面 / journalctl -b | 5–40 秒(最关键可优化部分) |
| 5 | 系统就绪 | 登录提示 / 显示管理器 / getty | 控制台登录或图形桌面 | — |
2. 每个阶段的理论细节与关键机制
阶段 1:固件阶段(BIOS / UEFI)
- UEFI 模式下:读取 EFI 系统分区(FAT32,通常 /boot/efi),加载 EFI 引导项(efibootmgr 管理)。
- 寻找 Bootxxxx 变量中优先级最高的 .efi 文件(通常是 grubx64.efi)。
- 安全启动(Secure Boot)启用时,只允许签名过的引导加载器和内核执行。
阶段 2:引导加载器(GRUB2 为主,少数用 systemd-boot)
- GRUB 读取 /boot/grub/grub.cfg(由 update-grub 生成)。
- 加载选中的内核(vmlinuz-x.x.x-generic)和对应的 initramfs(initrd.img)。
- 传递内核命令行参数(/proc/cmdline):quiet splash、root=UUID=xxx、ro、systemd.unit=xxx 等。
- Ubuntu Server 默认不显示 GRUB 菜单(GRUB_TIMEOUT=0),除非按 Shift 或 Esc。
阶段 3:内核初始化(Kernel + initramfs)
- 内核解压 initramfs(微型根文件系统,包含必要模块、udev、busybox 等)。
- initramfs 中的 /init 脚本(通常是 systemd 的早期版本或 dracut 生成的脚本)负责:
- 加载模块(modprobe)
- 激活 LVM / RAID / 加密(cryptsetup)
- 挂载真实根文件系统(switch_root)
- 内核参数 root= 指定真实根设备,rootfstype= 指定文件系统类型。
- 成功 switch_root 后,内核执行 /sbin/init(符号链接 → /lib/systemd/systemd)。
阶段 4:systemd 初始化(PID 1 的世界)
systemd 作为 PID 1 启动后,立即进入并行依赖激活模式,不再是传统的顺序脚本执行。
核心概念:
- Unit:systemd 的最小管理单元,共 11 种类型,最常见:
- .service(服务)
- .target(同步点 / 状态组)
- .mount / .automount
- .socket(socket 激活)
- .timer(定时任务)
- .path(路径监控触发)
- Target:相当于旧 SysV 的 runlevel,但更灵活,是“目标状态”而非级别。
- basic.target:最基础系统(所有服务 After=basic.target)
- multi-user.target:无图形多用户模式(Server 默认)
- graphical.target:带图形界面(桌面默认)
- default.target:启动时实际激活的目标(通常软链接到 multi-user.target 或 graphical.target)
启动逻辑:
- systemd 读取 /etc/systemd/system/default.target(或内核参数 systemd.unit=)
- 递归解析依赖(Wants=、Requires=、After=、Before=)
- 并行启动所有非阻塞单元(大量服务同时启动)
- 等待所有 Required 依赖满足
- 达到 default.target → 视为开机完成
关键同步点(target):
- sysinit.target → 基本系统初始化(fsck、swap、模块加载)
- local-fs.target → 本地文件系统挂载完成
- network.target → 网络配置完成(但不保证连通)
- network-online.target → 网络真正可达(需 wait-online 服务)
- multi-user.target → 命令行就绪
- getty.target → 控制台登录提示
3. 服务管理机制的核心理论
systemd 的服务管理远超传统 init 的启动/停止脚本,它引入了现代化的特性:
- 依赖类型:
- Wants=:弱依赖(失败不影响本单元)
- Requires=:强依赖(失败则本单元也失败)
- Requisite=:更严格(依赖已激活,否则本单元不启动)
- BindsTo=:跟随依赖生死(依赖停止则本单元也停止)
- 启动顺序:
- After= / Before=:纯顺序关系,不影响激活
- 推荐使用 After= + Wants= / Requires= 的组合
- 服务类型(Type=):
- simple(默认):启动即认为就绪
- forking:启动后 fork 子进程,父进程退出
- oneshot:运行一次后结束(脚本常用)
- notify:服务通过 sd_notify() 通知就绪
- dbus:等待特定 D-Bus name 出现
- 重启策略(Restart=):
- no / on-success / on-failure / on-abnormal / on-watchdog / on-abort / always
- 资源控制(cgroup v2):
- CPUQuota=、MemoryMax=、IOWeight=、DeviceAllow= 等
- ProtectSystem=、PrivateTmp=、NoNewPrivileges= 等安全沙箱
- 激活方式:
- 传统:开机启动(WantedBy=multi-user.target)
- socket 激活:有连接到来才启动(极致按需)
- path 激活:文件/目录变化触发
- timer 激活:定时 / 周期执行
4. 生产环境中理解与优化的关键点
- 开机慢最常见元凶:network-online.target 等待不存在的接口、远程挂载超时、Plymouth 等待、phased updates 延迟服务。
- 诊断启动瓶颈:systemd-analyze blame、systemd-analyze critical-chain、systemd-analyze plot > boot.svg
- 禁用不必要服务:systemctl mask(而非 disable)防止被依赖拉起。
- 自定义 target:可创建 mini.target 只启动特定服务,用于容器、嵌入式或快速恢复场景。
- cgroups v2 + systemd:默认统一层级,资源隔离更精细,OOM killer 更可控。
理解 systemd 的依赖图和服务激活模型后,你就能从“重启后不知道为什么卡住”转变为“精准定位第几秒哪个单元在等什么”。