强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

systemd 教程 / systemd 简介与架构

systemd 简介与架构

一、历史背景

1.1 从 System V init 到 systemd

Linux 系统启动过程经历了三代初始化系统:

代际 系统 引入时间 特点
第一代 System V init 1983 (Unix) 串行启动,Shell 脚本驱动
第二代 Upstart 2006 (Ubuntu) 事件驱动,并行启动
第三代 systemd 2010 (Fedora) 并行启动,依赖管理,全面接管

systemd 由 Lennart Poettering(红帽工程师)于 2010 年首次发布,最初目标是替代传统的 System V init 系统。如今 systemd 已经远远超出"初始化系统"的范畴,成为 Linux 系统的基础服务管理框架。

# 查看当前系统的 systemd 版本
systemctl --version

输出示例:

systemd 252 (252.36-1~deb12u1)
+PAM +AUDIT +SELINUX +APPARMOR +IMA +SMACK +SECCOMP +GCRYPT -GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBFDISK +PCRE2 -PWQUALITY +P11KIT +QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB +ZSTD -BPF_FRAMEWORK -XKBCOMMON +UTMP +SYSVINIT default-hierarchy=unified

1.2 systemd 的设计哲学

systemd 遵循以下设计原则:

  • 并行化启动:尽可能同时启动无依赖关系的服务
  • 按需激活:通过 socket/D-Bus 激活,减少不必要的启动
  • 依赖管理:声明式依赖关系,自动解析
  • 统一日志:journald 提供结构化二进制日志
  • CGroup 管理:每个服务独立的资源隔离

二、三代初始化系统详细对比

特性 System V init Upstart systemd
启动方式 串行 事件驱动 并行 + 依赖
服务定义 Shell 脚本 事件配置 Unit 文件
依赖管理 手动排序 事件触发 声明式
日志系统 syslog syslog journald
CGroup 集成 有限 深度集成
服务监控 有限 自动重启
进程追踪 PID 文件 D-Bus CGroup + PID
启动速度 较快
配置语法 Shell 自有语法 INI 风格

2.1 System V init 的局限

# 传统 SysVinit 启动脚本示例
cat /etc/init.d/networking

System V init 依赖 /etc/inittab 定义运行级别,服务脚本放在 /etc/init.d/ 下,通过符号链接到 /etc/rcN.d/ 目录控制启动顺序。缺点包括:

  • 串行启动,速度慢
  • Shell 脚本复杂、难以维护
  • 无法自动重启崩溃的服务
  • 缺乏统一的服务管理接口

三、systemd 架构总览

3.1 核心组件

systemd 不仅仅是一个 init 系统,而是一组相互协作的组件:

                    ┌─────────────────────────┐
                    │      systemd (PID 1)      │
                    │   系统与服务管理器核心     │
                    └───────────┬─────────────┘
                                │
        ┌───────────┬───────────┼───────────┬───────────┐
        │           │           │           │           │
   ┌────▼────┐ ┌────▼────┐ ┌────▼────┐ ┌────▼────┐ ┌────▼────┐
   │journald │ │networkd │ │resolved │ │logind   │ │timesyncd│
   │日志系统 │ │网络管理 │ │DNS解析  │ │登录管理 │ │时间同步 │
   └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘
组件 守护进程 功能
systemd PID 1 核心进程管理器
journald systemd-journald 结构化日志收集与查询
networkd systemd-networkd 网络配置管理
resolved systemd-resolved DNS 解析与缓存
logind systemd-logind 用户登录与会话管理
timesyncd systemd-timesyncd NTP 时间同步
udevd systemd-udevd 设备管理
home systemd-homed 用户主目录管理

3.2 PID 1 的特殊角色

systemd 作为 PID 1 运行,承担以下特殊职责:

# 确认 systemd 是 PID 1
ps -p 1 -o comm=

输出:

systemd

PID 1 的特殊性:

  • 孤儿进程回收:所有孤儿进程会被 reattach 到 PID 1
  • 信号处理:PID 1 不响应 SIGTERM(防止意外杀掉 init)
  • CGroup 树根:所有进程都位于 systemd 管理的 CGroup 树中

⚠️ 注意:不要尝试 kill PID 1,这会导致系统立即重启(systemctl reboot 是正确方式)。


四、Unit 类型

systemd 管理的基本对象称为 Unit,每种 Unit 类型对应不同的系统资源:

Unit 类型 文件后缀 用途
Service .service 系统服务(最常用)
Socket .socket Socket 激活
Timer .timer 定时任务(替代 cron)
Mount .mount 文件系统挂载
Automount .automount 按需自动挂载
Swap .swap 交换分区管理
Path .path 路径监控触发
Target .target 启动目标(分组单元)
Device .device 设备单元(udev)
Slice .slice CGroup 资源切片
Scope .scope 外部创建的 CGroup
Slice .slice CGroup 层级组织
# 列出所有 Unit 类型
systemctl list-unit-files --type=help

五、Unit 文件路径与优先级

5.1 三个搜索路径

systemd 按以下路径搜索 Unit 文件:

路径 用途 优先级
/etc/systemd/system/ 系统管理员自定义(最高优先级) ★★★
/run/systemd/system/ 运行时生成(重启后丢失) ★★
/usr/lib/systemd/system/ 软件包安装的默认文件

💡 提示/usr/local/lib/systemd/system/ 在某些发行版中也支持,用于手动安装的软件。

5.2 用户级 Unit 路径

路径 用途
~/.config/systemd/user/ 用户自定义(最高优先级)
/run/user/<UID>/systemd/user/ 运行时用户单元
/usr/lib/systemd/user/ 软件包安装的用户单元

5.3 优先级规则

当同名 Unit 文件存在于多个路径时,systemd 按优先级加载:

# 查看某 Unit 的实际加载路径
systemctl cat sshd.service

输出会显示完整路径,高优先级目录中的文件会完全覆盖低优先级目录中的同名文件(非合并)。

# 查看 Unit 文件的搜索路径
systemd-analyze unit-paths

输出示例:

/etc/systemd/system.control
/run/systemd/system.control
/run/systemd/transient
/run/systemd/generator.early
/etc/systemd/system
/etc/systemd/system.attached
/run/systemd/system
/run/systemd/system.attached
/run/systemd/generator
/usr/local/lib/systemd/system
/usr/lib/systemd/system
/run/systemd/generator.late

⚠️ 注意:直接修改 /usr/lib/systemd/system/ 下的文件会在软件包更新时被覆盖。正确做法是将自定义配置放在 /etc/systemd/system/ 中。


六、发行版支持情况

发行版 默认使用 systemd 备注
Fedora ✅ (2011, v15) systemd 的首发平台
Ubuntu ✅ (2014, v14.10) 从 Upstart 迁移
Debian ✅ (2015, v8) 经过社区投票决定
CentOS/RHEL ✅ (v7+) RHEL 7 开始
Arch Linux ✅ (2012) 较早采纳
openSUSE ✅ (v12.1+)
Alpine Linux 使用 OpenRC
Void Linux 使用 runit
Gentoo 可选 默认 OpenRC
# 检查当前系统是否使用 systemd
ps -p 1 -o comm= | grep -q systemd && echo "使用 systemd" || echo "未使用 systemd"

七、快速上手:第一个 systemctl 命令

# 查看 sshd 服务状态
systemctl status sshd

# 启动/停止/重启服务
systemctl start nginx
systemctl stop nginx
systemctl restart nginx

# 开机自启
systemctl enable nginx

八、生产场景

场景:快速排查系统启动问题

# 查看本次启动耗时
systemd-analyze

# 查看启动链中最慢的服务
systemd-analyze blame | head -20

# 查看关键路径(critical chain)
systemd-analyze critical-chain

输出示例:

The time after the unit is active or started is printed after the "@" character.
The time the unit takes to start is printed after the "+" character.

multi-user.target +3.102s
└─nginx.service @1.891s +210ms
  └─network.target @1.880s
    └─NetworkManager.service @1.203s +676ms
      └─basic.target @1.198s
        └─sockets.target @1.197s
          └─dbus.socket @1.196s
            └─sysinit.target @1.190s
              └─systemd-update-utmp.service @1.175s +14ms

九、扩展阅读