当前位置:首页>Linux>沙场点兵:systemd——现代 Linux 的 init 系统

沙场点兵:systemd——现代 Linux 的 init 系统

  • 2026-10-11 07:31:28
沙场点兵:systemd——现代 Linux 的 init 系统
 

🏰 沙场点兵:systemd——现代 Linux 的 init 系统

❖ ❖ ❖

故事开头

2010 年,一个名叫 Lennart Poettering 的德国程序员做了一个决定——他要重写 Linux 的 init 系统。

init 是 Linux 启动的第一个进程(PID 1),负责启动其他所有服务。传统的 init 是串行的——启动完 A,再启动 B,再启动 C。启动一台服务器,需要几分钟。

Lennart 想让它并行启动——同时启动 A、B、C,启动时间缩短到几秒钟。

这个新项目叫 systemd。

今天,systemd 已经运行在全球 90% 以上的 Linux 发行版上。它不仅是 init 系统,更是 Linux 的"大管家"。

❖ ❖ ❖

一、init 的困境

1.1 传统的 init

在 systemd 之前,Linux 使用传统的 init 系统(SysV init)。

它的工作方式很简单:

  1. 内核启动 init 进程(PID 1)
  2. init 读取 /etc/inittab 文件
  3. 按顺序执行启动脚本(/etc/init.d/ 目录下的脚本)
  4. 启动完成,进入登录界面

问题是什么?

串行启动。 脚本 A 执行完,才执行脚本 B。即使 A 和 B 没有依赖关系,也必须等 A 完成。

一台服务器启动需要 2-3 分钟——大部分时间花在等待磁盘 I/O 和网络初始化上。

1.2 启动脚本的混乱

传统的启动脚本是 shell 脚本。每个服务的启动逻辑都不一样:

  • 有的脚本检查依赖
  • 有的脚本不检查
  • 有的脚本启动失败后不报错
  • 有的脚本启动成功后不记录

比喻:

  • 传统 init 是"手工生产线"——每个工人按顺序干活
  • 服务启动是"盲人摸象"——不知道哪个服务先启动
❖ ❖ ❖

二、systemd 的诞生

2.1 并行启动

systemd 的核心创新:并行启动。

它不按顺序执行脚本,而是分析服务之间的依赖关系,同时启动没有依赖的服务。

传统 init:A → B → C → D → E(串行,3 分钟)
systemd:  A ─┐
        B ─┼→ D → E(并行 + 依赖,30 秒)
        C ─┘

比喻:

  • 传统 init 是"排队买票"——一个人买完,下一个人才能买
  • systemd 是"开多个窗口"——同时服务多个人

2.2 声明式配置

systemd 使用声明式配置。

每个服务有一个 .service 文件,描述:

  • 服务怎么启动
  • 依赖什么
  • 失败后怎么办
[Unit]
Description=My Web Server
After=network.target
Requires=postgresql.service

[Service]
Type=simple
ExecStart=/usr/bin/my-web-server
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

比喻:

  • 传统 init 是"命令式"——"先启动 A,再启动 B"
  • systemd 是"声明式"——"我想要 A 和 B 都运行,A 依赖 B"

2.3 统一的管理

systemd 统一管理所有服务。

不再需要手写 shell 脚本。systemd 提供统一的命令:

# 启动服务
systemctl start nginx

# 停止服务
systemctl stop nginx

# 重启服务
systemctl restart nginx

# 查看服务状态
systemctl status nginx

# 设置开机启动
systemctl enable nginx

# 查看服务日志
journalctl -u nginx
❖ ❖ ❖

三、systemd 的核心概念

3.1 Unit

Unit 是 systemd 的基本单位。

systemd 管理各种类型的 Unit:

类型后缀说明
Service.service服务(最常见)
Socket.socketSocket 激活
Target.target运行级别(类似)
Timer.timer定时器(替代 cron)
Mount.mount挂载点
Path.path路径监控

比喻:

  • Unit 是"任务"——systemd 管理各种任务

3.2 Target

Target 是 systemd 的"运行级别"。

传统的运行级别(runlevel)太简单了——只有 0-6 七个级别。systemd 的 Target 更灵活:

Target说明
multi-user.target多用户模式(无图形界面)
graphical.target图形界面模式
network.target网络就绪
local-fs.target本地文件系统挂载完成

比喻:

  • Target 是"里程碑"——到达某个里程碑,表示某些服务已经启动

3.3 依赖管理

systemd 自动管理服务之间的依赖。

[Unit]
Description=My Web Server
After=network.target postgresql.service
Requires=postgresql.service
Wants=redis.service
  • After=network.target — 在网络就绪后启动
  • Requires=postgresql.service — 强依赖 PostgreSQL,PostgreSQL 挂了,这个服务也停
  • Wants=redis.service — 弱依赖 Redis,Redis 挂了,这个服务继续运行

比喻:

  • Requires 是"必须"——没有 PostgreSQL,Web 服务器无法运行
  • Wants 是"最好有"——有 Redis 更好,没有也能运行
❖ ❖ ❖

四、systemd 的高级功能

4.1 Socket 激活

Socket 激活(Socket Activation)是 systemd 的杀手级功能。

传统方式:服务启动时,打开 Socket,监听端口。即使没有请求,服务也在运行,占用内存。

Socket 激活:systemd 先打开 Socket,监听端口。有请求时,才启动服务,把 Socket 文件描述符传给服务。

# nginx.socket
[Socket]
ListenStream=80

# nginx.service
[Service]
ExecStart=/usr/bin/nginx

好处:

  • 服务按需启动——没有请求,不占用资源
  • 启动更快——不需要等服务启动,Socket 已经就绪
  • 请求不丢失——systemd 帮服务排队

比喻:

  • 传统方式是"餐厅提前开门"——没客人也要开门
  • Socket 激活是"按需开门"——有客人了才开门

4.2 Timer

Timer 替代 cron,提供更精细的定时任务管理。

# backup.timer
[Unit]
Description=Daily Backup Timer

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target
# backup.service
[Unit]
Description=Daily Backup Service

[Service]
ExecStart=/usr/local/bin/backup.sh

优势:

  • 支持日历事件(daily、weekly、monthly)
  • 支持相对时间(OnBootSec、OnUnitActiveSec)
  • 支持 Persistent=true——错过执行时间,下次启动时补执行

比喻:

  • cron 是"闹钟"——到时间响
  • Timer 是"智能闹钟"——错过了会补

4.3 日志管理

systemd 有自己的日志系统:journald。

# 查看所有日志
journalctl

# 查看特定服务的日志
journalctl -u nginx

# 查看今天的日志
journalctl --since today

# 实时查看日志
journalctl -f -u nginx

# 查看内核日志
journalctl -k

优势:

  • 结构化日志——按服务、时间、优先级过滤
  • 自动轮转——不需要手动配置 logrotate
  • 二进制格式——更高效
❖ ❖ ❖

五、systemd 与容器

5.1 容器中的 PID 1

在容器中,PID 1 是什么?

传统容器: PID 1 是应用进程(如 nginx)。

问题:

  • 应用进程不是 init 系统,不会回收僵尸进程
  • 应用进程不会处理信号(如 SIGTERM)

最佳实践: 容器中使用轻量级 init 系统(如 tini、dumb-init)。

# 使用 tini 作为 PID 1
ENTRYPOINT ["/usr/bin/tini", "--"]
CMD ["nginx", "-g", "daemon off;"]

5.2 systemd 在容器中的角色

systemd 不适合在容器中运行。

原因:

  • systemd 需要访问内核功能(cgroup、namespace)
  • 容器通常不运行完整的 systemd
  • 容器应该"一个进程一个容器"

但 systemd 在容器编排中有重要角色:

  • K8s 的节点通常是运行 systemd 的 Linux 发行版
  • systemd 管理容器运行时(如 containerd、kubelet)
  • systemd 的 Socket 激活可以用于容器服务发现
❖ ❖ ❖

六、systemd 的争议

6.1 为什么有争议?

systemd 是 Linux 历史上最有争议的项目之一。

批评意见:

  1. 功能膨胀 — systemd 不仅做 init,还做日志、定时、网络、登录管理……它变成了一个"操作系统"。
  2. 不兼容 Unix 哲学 — Unix 哲学是"做好一件事",systemd 做太多事。
  3. 闭源组件 — 某些 systemd 组件依赖闭源库。
  4. 强制升级 — 某些发行版强制使用 systemd,不提供选择。

6.2 支持者的观点

支持者认为:

  1. 解决了实际问题 — 并行启动、依赖管理、Socket 激活,都是真实需求。
  2. 统一标准 — 以前每种发行版有自己的 init 系统,现在统一了。
  3. 现代特性 — 日志、定时器、资源限制,都是现代操作系统需要的。

6.3 替代方案

如果你不喜欢 systemd,还有替代方案:

  • OpenRC — Gentoo、Alpine Linux 使用
  • runit — 轻量级,适合容器
  • s6 — 另一个轻量级 init
  • sysvinit — 传统 init,已废弃

但现实是:systemd 已经赢了。 绝大多数 Linux 发行版(Ubuntu、Debian、CentOS、Fedora、RHEL、SUSE)都使用 systemd。

❖ ❖ ❖

总结

systemd 是现代 Linux 的 init 系统。

  • 并行启动 — 缩短启动时间
  • 声明式配置 — 描述服务怎么启动
  • 依赖管理 — 自动处理服务依赖
  • Socket 激活 — 按需启动服务
  • 日志管理 — journald 统一管理日志

常用命令:

systemctl start/stop/restart/status 
systemctl enable/disable 
journalctl -u 

比喻:

  • systemd 是"大管家"——管理所有服务
  • Unit 是"任务"——各种类型的任务
  • Target 是"里程碑"——到达某个阶段

理解 systemd,就理解了 Linux 服务管理的现代方式——没有 systemd,就没有现代 Linux 服务器。

下篇预告:

systemd 解决了"服务管理"的问题。有了这些基础,我们就能更好地理解六侠演武场的架构了。明天我们再次移步工地去看看。

—— 第八章 · 完 ——

⚙️🔧📋

systemd:现代 Linux 的 init 系统

敬请期待:Docker 的诞生

🐼 Po & 🦐 OpenClaw

2026 年 6 月 7 日 于狮城云端

最新文章

随机文章