前言
🙇观前提示:作者在撰写过程中,调整了结构数次,如有跳跃逻辑不清之处,还请谅解
作者一直在使用 systemd 进行管理 Linux 的进程,但是却没有去细致了解过运行原理和架构。
所以决定搜一搜,学一学,看一看。
有很多前辈们讲的非常好,所以这篇文章呢,很多地方都是 CV的。
正文
1. 介绍
这里引用自官方原话
systemd 是一套 Linux 系统的基本构件。它提供了一个系统和服务管理器,作为 PID 1 运行,并启动系统的其他部分。
systemd 支持 SysV 和 LSB 启动脚本,并可替代 sysvinit。
其他部分包括日志守护进程,用于控制主机名、日期、地域等基本系统配置的实用程序,维护登录用户、运行容器和虚拟机、系统账户、运行时目录和设置的列表,以及管理简单网络配置、网络时间同步、日志转发和名称解析的守护进程。
偷了一个图

2. 系统管理
systemd 是一组命令,设计到系统管理的方方面面
2.1 systemctl
systemctl 是 Systemd 的主命令,用于管理系统。
2.2 systemd-analyze
这个命令我还真非常少用
systemd-analyze命令用于查看启动耗时。
这里测试一手

2.3 hostnamectl
hostnamectl命令用于查看当前主机的信息。

2.4 localectl
localectl命令用于查看本地化设置。
说个题外话,如果把参数调整成中文的话,使用 man 可以很方便的查阅命令要如何使用
项目地址: manpages-zh
如果你只想让 man 命令显示中文,而不改变整个系统的语言设置,可以创建一个别名
学好英语不是更好吗 (作者是语言苦手😭
这样输入 cman <option> 就能查看对应命令的中文手册

2.5 timedatectl

💡:其实作者的文章很多都是翘课的时候写的
2.6 loginctl
loginctl命令用于查看当前登录的用户。
3. Unit(单元)
3.1 Unit 介绍
Systemd 可以管理所有系统资源。不同的资源统称为 Unit(单元)。
3.2 Unit 的类型
Unit 共分为 12 种。
| 单元类型 | 文件后缀 | 描述 |
|---|---|---|
| Service | .service | 定义了系统服务,包括启动,重启,关闭服务的相关指令 |
| Target | .target | 定义了一组单元的集合,通常作为单元启动的同步点,某个target启动成功就意味着一组相关的service启动成功 |
| Automount | .automount | 定义了系统引导时会进行自动挂载的挂载点 |
| Device | .device | 定义了由systemd管理的硬件设备 |
| Mount | .mount | 定义了由systemd管理的文件系统挂载点 |
| Path | .path | 定义了一条用于基于路径激活服务的文件路径。例如,可以基于某一条文件路径的状态(是否存在等)来启动某个服务。 |
| Scope | .scope | 定义了来自systemd总线接口的信息,通常用来管理额外的系统进程 |
| Slice | .slice | 定义了资源限额,基于Linux cgroup nodes实现。 |
| Snapshot | .snapshot | 定义了一次当前的systemd状态,通常在对systemd做修改后回滚使用 |
| Socket | .socket | 定义了进程间通信使用的socket,往往socket会与service相关联 |
| Swap | .swap | 定义了系统中的交换空间 |
| Timer | .timer | 定义了一个定时激活另一个单元的定时器 |
3.3 Unit 之间的依赖关系
Unit 之间并非孤立,它们通过依赖关系组织在一起。
依赖关系:systemd 通过 Wants 和 Requires 等指令定义依赖。例如,A Wants B,意味着启动 A 的时候,systemd 也会尝试启动 B。Requires 则是更强的“必须”依赖。
Target:Target 是一种特殊的 Unit,它本身不执行任何操作,而是作为一个“单元组”的引用点。例如,multi-user.target 包含了所有在多用户命令行模式下需要运行的服务和单元。当系统进入 multi-user.target 状态时,systemd 会确保该 Target 依赖的所有 Unit 都已启动。
3.4 Target
查资料的时候,看到有篇文讲的很好, 这里给原话搬过来
《一篇搞懂》系列之三——systemdTarget Unit理解起来并不难,它就是一组Units的集合。这就跟学生时代升旗仪式一样,每个班(Target)有很多学生(Units),只有当每位学生(Units)都到齐之后,这个班(Target)才允许进入操场。当所有的班(Target)都进入操场后,升旗仪式(default. Target)才会进行。
所以,在 systemd 架构下,系统的启动方式可以这样理解:systemd 通过 default. Target 来启动系统,什么时候 default. Target 准备就绪,系统就认为启动成功。
启动计算机的时候,需要启动大量的 Unit。如果每一次启动,都要一一写明本次启动需要哪些 Unit,显然非常不方便。Systemd 的解决方案就是 Target。
简单说,Target 就是一个 Unit 组,包含许多相关的 Unit 。启动某个 Target 的时候,Systemd 就会启动里面所有的 Unit。从这个意义上说,Target 这个概念类似于"状态点",启动某个 Target 就好比启动到某种状态。

3.5 Unit 配置文件
3.5.1 概述
在 Systemd 中,每一个 Unit(单元)都有一个配置文件,用来告诉 Systemd 该如何启动和管理这个 Unit。
单元文件是 ini 风格的纯文本文件。封装了有关下列对象的信息: 服务 (service)、套接字 (socket)、设备 (device)、挂载点 (mount)、自动挂载点 (automount)、启动目标 (target)、交换分区或交换文件 (swap)、被监视的路径 (path)、任务计划 (timer)、资源控制组 (slice)、一组外部创建的进程 (scope)。
我们来看看系统有哪些 Unit:
systemctl list-units 命令可以查看当前系统的所有 Unit 。

接下来,我们以 nginx 为例,查看其 Unit 的配置文件
systemctl cat <unit.service> 可以查看配置文件:
从上文可以看出,配置文件主要分为三个区块,内容以键值对呈现。
以下为 Unit 配置文件的详细介绍文章:
3.2.2 Unit 配置文件存储的位置
Systemd 默认会从目录 /etc/systemd/system/ 读取配置文件。不过,这个目录中的很多文件并不是实际的配置内容,而是 符号链接(快捷方式),它们指向 /usr/lib/systemd/system/ 目录中的真正配置文件。
/usr/lib/systemd/system/→ 存放系统提供的、真实的服务配置文件/etc/systemd/system/→ 存放用户或系统在运行时创建的符号链接(以及可能的自定义文件)、./system/启动系统服务(数据库、Web、网络服务)如:nginx./user/运行用户脚本、桌面程序自动启动、会话守护进程如:my-script.sh
3.2.3 Unit 的格式
单元配置文件这里只做部分的简述,这里可以去到详细介绍的文章
systemctl cat 命令可以查看配置文件的内容。
systenctl edit 可以覆盖更改
3.4 Unit 配置文件的状态
我们可以使用 systemctl list-unit-files 命令用于列出所有配置文件。
列表会显示出各种配置文件及状态。
但是具体状态需要使用 systemctl status 进行查看。

配置文件的各种状态:
| 状态 | 含义 | 说明 |
|---|---|---|
| enabled | 启用 | 在对应 target 下有符号链接,开机自动启动 |
| enabled-runtime | 临时启用 | 链接在 /run/systemd/system 下,重启后消失 |
| linked | 链接启用 | unit 不在标准路径下,而是被符号链接到 systemd 搜索路径中(持久) |
| linked-runtime | 临时链接启用 | 同上,但临时(位于 /run/systemd/system) |
| disabled | 禁用 | 没有符号链接到任何 target,需要手动启动 |
| static | 静态 | 无 [Install] 段,无法直接 enable/disable,仅作为依赖启动 |
| masked | 屏蔽 | unit 文件被符号链接到 /dev/null 永久禁止启动 |
| masked-runtime | 临时屏蔽 | 屏蔽符号链接在 /run/systemd/system,重启后恢复 |
| alias | 别名 | 该 unit 是另一个 unit 的别名(常见于服务提供者) |
| generated | 生成的 | 由 systemd 动态从其它配置生成的 unit,通常存放在 /run/systemd/generator.* |
| transient | 临时单元 | 运行时通过 D-Bus/systemd-run 创建,存活到运行结束 |
| bad | 无效 | 单元文件无效或损坏(配置格式错误、文件不存在等) |
4. Unit 的管理
4.1 实践:创建并管理一个自己的服务
多说无益,让我们动手实操,写一个试试
4.1.1 创建 Unit 配置文件
路径: /etc/systemd/system/simplehttp.service
这是一个使用 python3 在 8888 端口启动 http 服务的配置文件。
4.1.2 管理服务生命周期
刚刚我们写了一个用于测试的 Unit 配置,但是还没有启动
现在我们要先手动使用 systemctl daemon-reload 加载配置
然后查看一下 systemd 是否已经读取到
可以看到,服务已经加载进来了 (loaded),且并没有启动 (inactive dead),此外,我们还可以看到我们给服务写的描述 (My Simple HTTP Service)。
- 想要服务立即启动
systemctl start <servicename>
- 设置开机自启并立即启动
systemctl enable --now <servicename>
- 查看服务状态
systemctl status <servicename>
我们测试一下,可以清晰看到各种状态:
4.1.3 测试服务
服务启动了就测试一手
接着我们使用 systemctl status, 可以发现一条日志, 到此我们已经完成了一个 Unit 的配置。
4.1.4 修改服务
📌 属性写入后,如果想持久保存,建议通过 systemctl edit 写入 override. Conf;否则可能在重启 systemd 后丢失。
以 simplehttp 为例:systemctl edit simplehttp 会创建一个覆盖文件 /etc/systemd/system/simplehttp.service.d/override.conf 并在文本编辑器中打开它。你添加到该文件中的任何内容都将添加到现有的服务文件中。
添加自定义配置,例如

检查一下:
要替换可多次设置的选项,必须先清除该选项,否则覆盖文件将第二次添加该选项。
保存文件。systemd 会自动加载新的服务配置。
之后使用 systemd restart 重启服务即可

⚠️:如果要完全替换服务
使用systemctl edit --full,例如systemctl edit --full simplehttp.service。这样会创建/etc/systemctl/system/simplehttp.service,取代现有的服务文件。
4.2 Unit 的部分常用命令
systemd命令 | 作用 |
|---|---|
enable | 设置开机自动启动 |
disable | 取消开机自动启动 |
start | 立即启动 |
stop | 立即停止 |
restart | 停止并重启 |
kill | 杀死服务及子进程 |
reload | 不停止服务,重新加载配置(服务需支持) |
daemon-reload | systemd 重新读取修改过的 Unit 文件 |
status | 查看运行状态和日志 |
show | 查看所有底层属性 |
set-property | 动态设置属性 |
journalctl -u | 查看服务日志 |
1. 管理服务开机启动
示例:
📌 注意:enable / disable 改的是开机时自动启动与否,不影响当前是否正在运行。
要立即启动,需要用 start。
2. 启动 / 停止 / 重启 / 杀死
📌 kill 会根据 Unit 配置里的 KillMode 决定是杀掉主进程还是全部子进程(默认是全部)。
3. 重新加载配置
📌 注意:reload 是让服务自己重新读配置,daemon-reload 是让 systemd 本身重新读 Unit 文件。如果你改了 Unit 文件,一定要 daemon-reload。
4. 查看服务信息
📌 status 会给你当前运行状态、进程 ID、日志信息;show 适合脚本解析。
除了 status 命令,systemctl 还提供了三个查询状态的简单方法,主要供脚本内部的判断语句使用。
5. 修改运行时属性
📌 属性写入后,如果想持久保存,建议通过 systemctl edit 写入 override. Conf;否则可能在重启 systemd 后丢失。
6. 其他常用补充命令
7. 总结
enable / disable 管开机启动,start / stop / restart 管当前状态,reload / daemon-reload 管配置刷新,show / set-property 管属性配置。日志用 journalctl -u 查。
systemctl status 命令用于查看系统状态和单个 Unit 的状态。

5. Journalctl日志服务
一个合格的程序员要学会看日志
Systemd 统一管理所有 Unit 的启动日志。带来的好处就是,可以只用 journalctl 一个命令,查看所有日志(内核日志和应用日志)。
日志的配置文件是/etc/systemd/journald.conf。
思考
回顾过去,我写文章更多是为了记录——记录当时的思路,或者简单记下自己学到的知识。很多时候,并不是我已经真正理解透了,而只是先把东西写下来。
这次写文的过程让我有坡有些“便秘”。一边查资料,一边码字,写着写着就发现:前辈的文章写得真好,不知不觉就开始“这里搬一点,那里抄一点”。结果,文章缺少了属于我自己的主线和思考。
写到一半时,感觉越来越不对劲。于是我决定停下手来,把相关的内容全部重新梳理一遍——从头阅读、理解,再结合自己的思路和记忆,把文章重写。
当我最终用自己的话写出来时,过程虽然慢,但收获很大。不仅对内容理解得更深,也更清楚地意识到:写作不仅是记录,更是一次重新思考与内化的过程。
真得多写字,多社交,多说话。作者已经到了表达不出来自己的话,有时候需要 ai 润色表达出来了😭 明明我是
ENFP啊,怎么变成小阿宅了
码字学东西的时候还有个很重要的点,一定要多查资料翻资料,官方 Wiki 的东西很多时都写的非常棒!参考别人的文章,终究是吸取别人的理解,而不是自己的理解。
希望我也能做到写文引人入胜,一层套一层。
写草稿,写大纲是对的)