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

systemd 教程 / systemd 简介与架构

systemd 简介与架构

一、历史背景

1.1 从 System V init 到 systemd

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

代际系统引入时间特点
第一代System V init1983 (Unix)串行启动,Shell 脚本驱动
第二代Upstart2006 (Ubuntu)事件驱动,并行启动
第三代systemd2010 (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 initUpstartsystemd
启动方式串行事件驱动并行 + 依赖
服务定义Shell 脚本事件配置Unit 文件
依赖管理手动排序事件触发声明式
日志系统syslogsyslogjournald
CGroup 集成有限深度集成
服务监控有限自动重启
进程追踪PID 文件D-BusCGroup + 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解析  │ │登录管理 │ │时间同步 │
   └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘
组件守护进程功能
systemdPID 1核心进程管理器
journaldsystemd-journald结构化日志收集与查询
networkdsystemd-networkd网络配置管理
resolvedsystemd-resolvedDNS 解析与缓存
logindsystemd-logind用户登录与会话管理
timesyncdsystemd-timesyncdNTP 时间同步
udevdsystemd-udevd设备管理
homesystemd-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.socketSocket 激活
Timer.timer定时任务(替代 cron)
Mount.mount文件系统挂载
Automount.automount按需自动挂载
Swap.swap交换分区管理
Path.path路径监控触发
Target.target启动目标(分组单元)
Device.device设备单元(udev)
Slice.sliceCGroup 资源切片
Scope.scope外部创建的 CGroup
Slice.sliceCGroup 层级组织
# 列出所有 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

九、扩展阅读