Ubuntu 的启动流程和服务管理机制在现代版本(尤其是 16.04 之后)已经完全基于 systemd 体系。理解这个流程不仅能帮助你快速定位开机慢、启动失败、服务异常等问题,还能让你更深刻地理解 Linux 系统“从按下电源到出现登录提示”到底发生了什么。
以下内容以 Ubuntu 24.04 LTS 为基准(2026 年主流生产版本),按时间顺序完整拆解启动链路,并重点解析 systemd 的服务管理核心逻辑。
一、Ubuntu 启动完整流程(从 BIOS/UEFI 到用户登录)
固件阶段(BIOS / UEFI)
- 开机 → 主板固件自检(POST)
- 读取引导顺序 → 找到引导设备(通常是 /boot 分区或 ESP 分区)
- 加载引导加载器(Bootloader)
第一阶段引导加载器(Bootloader Stage 1) Ubuntu 默认使用 GRUB2
- GRUB 读取 /boot/grub/grub.cfg
- 显示 GRUB 菜单(可选择内核版本、进入 rescue mode)
- 加载选中的内核(vmlinuz)和初始内存盘(initrd / initramfs)
内核解压与 initramfs 执行
- 内核解压到内存
- 挂载 initramfs(临时根文件系统,包含最基本的驱动和工具)
- initramfs 中的 init 脚本运行,主要完成:
- 加载必要模块(硬盘控制器、文件系统、RAID、LVM、加密等)
- 挂载真实根文件系统(/)
- 切换控制权:switch_root 到真实根文件系统
systemd 成为 PID 1(真正的系统初始化)
- 内核启动后第一个用户态进程是 /lib/systemd/systemd(PID 1)
- systemd 读取默认 target(通常是 graphical.target 或 multi-user.target)
systemd 初始化阶段(按依赖顺序并行启动) systemd 把启动过程分解为多个 单元(unit),按依赖关系并行执行。主要阶段包括:
- sysinit.target 最早执行的基本系统初始化(挂载 /proc、/sys、/dev、设置主机名、加载模块等)
- basic.target 更基础的服务(日志、临时目录、设备节点等)
- multi-user.target(服务器默认) / graphical.target(桌面默认) 核心服务、网络、登录管理器等
- getty.target → 启动终端登录(ctrl+alt+F1~F6)
- (桌面版额外)display-manager.service → gdm / sddm / lightdm 等图形登录界面
用户登录阶段
- 控制台登录:getty → login → shell
- SSH 登录:sshd.service → PAM 认证 → 用户 shell
- 图形登录:display manager → greeter → 用户会话(systemd –user)
二、systemd 的核心设计理念与服务管理机制
systemd 取代 SysV init 和 Upstart 的根本原因是“并行化 + 声明式 + 依赖管理 + 状态跟踪”。
单元(Unit)的五种主要类型
类型 文件后缀 主要作用 Service .service 守护进程、服务程序 Target .target 同步点、组服务(类似 runlevel) Socket .socket 延迟启动(socket activation) Mount .mount 自动挂载文件系统 Device / Path / Timer 等 其他触发器 依赖关系(最核心机制)
- Wants / Requires / Requisite:软/硬依赖
- After / Before:启动顺序
- Conflicts:互斥
- PartOf / BindsTo:跟随关系
典型写法示例(/lib/systemd/system/nginx.service):
text[Unit] Description=A high performance web server... After=network.target remote-fs.target nss-lookup.target [Service] Type=forking ExecStart=/usr/sbin/nginx ExecReload=/usr/sbin/nginx -s reload Restart=on-failure [Install] WantedBy=multi-user.target启动类型(Type=)决定服务行为
- simple(默认):前台进程,systemd 认为主进程就是 ExecStart
- forking:启动后 fork 出子进程并退出(经典 daemon)
- oneshot:执行一次就结束(脚本、挂载)
- notify:服务通过 sd_notify 通知 systemd“我准备好了”
- idle:延迟到其他任务完成后启动
socket activation(现代特性)
systemd 可以先监听端口,真正需要时才启动服务(节省资源、加快开机)。 典型例子:sshd.socket + sshd@.service
重启策略(Restart=)
- no / always / on-success / on-failure / on-abnormal / on-watchdog / on-abort
三、常用管理命令与排查思路
- 查看启动耗时:systemd-analyze / systemd-analyze blame
- 查看当前 target:systemctl get-default
- 切换运行级别:systemctl isolate multi-user.target
- 服务状态:systemctl status 服务名
- 日志:journalctl -u 服务名 -b
- 依赖关系树:systemctl list-dependencies multi-user.target
- 开机失败单元:systemctl –failed
四、总结:systemd 带来的本质变化
- 从“串行等待”到“声明依赖 + 并行启动”
- 从“脚本驱动”到“单元文件 + 属性驱动”
- 从“难以追踪”到“journalctl + cgroups 全面可观测”
- 从“重启即重载”到“支持 socket activation、自动重启、状态通知”
理解了这个启动链路和服务管理机制后,你会发现:
- 开机慢 → systemd-analyze blame 找耗时单元
- 服务启动失败 → journalctl -u -b -xe
- 依赖顺序错乱 → 检查 After/Wants/Requires
- 端口没起来 → 检查 socket unit 或 Type= 是否正确
systemd 虽然复杂,但一旦掌握其声明式依赖模型,你对 Linux 系统启动的掌控力会提升一个数量级。这也是为什么 Ubuntu、Debian、Fedora、RHEL 等几乎所有主流发行版都全面拥抱它的根本原因。