systemd单元文件和配置片段
systemd 单元文件(unit file)= 告诉 systemd”一个东西是什么、怎么启动、什么时候启动”。 配置片段(drop-in)= 不修改原文件,只对某个单元进行局部覆盖/追加。
1. 什么是 systemd 单元(Unit)?
systemd 管理的对象都叫 Unit。
常见类型:
.service 服务
.target 一组 Unit 的目标/状态
.mount 挂载点
.automount 自动挂载
.socket Socket
.device 设备
.timer 定时器
.path 路径监控
.swap 交换分区/交换文件
例如:
sshd.service
sddm.service
NetworkManager.service
systemd 看到:
sshd.service
就知道:
“这是一个 SSH 服务,我需要按照它的 Unit 定义来管理它。“
2. 什么是 Unit 文件?
Unit 文件就是描述这个 Unit 的配置文件。
例如:
/usr/lib/systemd/system/sshd.service
里面可能类似:
[Unit]
Description=OpenSSH server daemon
After=network.target
[Service]
ExecStart=/usr/bin/sshd -D
Restart=on-failure
[Install]
WantedBy=multi-user.target
可以把它理解成一个”服务说明书”。
3. Unit 文件的三个常见部分
[Unit]
描述:
这个 Unit 和其他 Unit 的关系。
例如:
[Unit]
Description=OpenSSH server daemon
After=network.target
其中:
Description
是描述。
After=network.target
表示:
sshd 的启动顺序排在
network.target之后。
注意:
After 不代表”依赖”。
真正表达依赖关系的常见指令是:
Requires=
Wants=
[Service]
描述:
这个服务具体怎么运行。
例如:
[Service]
ExecStart=/usr/bin/sshd -D
Restart=on-failure
ExecStart:
ExecStart=/usr/bin/sshd -D
就是告诉 systemd:
启动这个 Service 时执行什么程序。
[Install]
描述:
这个 Unit 被 enable 时,应该加入哪个 target。
例如:
[Install]
WantedBy=multi-user.target
然后:
systemctl enable sshd.service
systemd 就会根据 [Install] 创建相应的启用关系。
4. /usr/lib/systemd/system 是什么?
Arch 中你经常会看到:
/usr/lib/systemd/system/
这里通常保存软件包提供的 Unit 文件。
例如:
/usr/lib/systemd/system/
├── sshd.service
├── sddm.service
├── NetworkManager.service
└── systemd-logind.service
这些一般属于:
软件包提供的默认配置。
因此通常不要直接修改这里的 Unit 文件。
原因很简单:
pacman 更新软件
↓
软件包重新安装 Unit
↓
你手动修改的内容可能被覆盖
5. /etc/systemd/system 又是什么?
这是管理员自己的 Unit 配置区域。
例如你自己创建:
/etc/systemd/system/myapp.service
systemd 会读取它。
一般可以记:
/usr/lib/systemd/system/
↓
软件包提供的默认 Unit
/etc/systemd/system/
↓
管理员自己的 Unit / 覆盖配置
而 /etc 的优先级更高。
6. 那什么是”配置片段”?
假设系统原来的:
/usr/lib/systemd/system/sshd.service
是软件包提供的。
你只想修改:
Restart=always
你完全没必要复制整个 sshd.service 到 /etc。
可以创建:
/etc/systemd/system/sshd.service.d/
然后:
/etc/systemd/system/sshd.service.d/override.conf
里面只写:
[Service]
Restart=always
这个文件就叫:
drop-in configuration / 配置片段
7. 为什么叫 drop-in?
因为 systemd 会把它”插入”原来的 Unit 配置中。
原始:
/usr/lib/systemd/system/sshd.service
配置片段:
/etc/systemd/system/sshd.service.d/override.conf
最终 systemd 理解成:
原 Unit
+
drop-in
↓
最终配置
因此你不需要复制整个 Unit。
8. systemctl edit 就是在干这个
例如:
systemctl edit sshd.service
systemd 会让你编辑:
/etc/systemd/system/sshd.service.d/override.conf
例如输入:
[Service]
Restart=always
保存后:
/usr/lib/systemd/system/sshd.service
+
/etc/systemd/system/sshd.service.d/override.conf
↓
systemd最终配置
这就是非常推荐的修改方式。
9. 为什么不直接修改 /usr/lib/…?
假设原始文件:
/usr/lib/systemd/system/sddm.service
你直接修改:
[Service]
Restart=always
升级 SDDM 后:
pacman -Syu
↓
更新 sddm
↓
/usr/lib/systemd/system/sddm.service
↓
可能被新的文件覆盖
而如果使用:
/etc/systemd/system/sddm.service.d/override.conf
那么:
软件包更新
↓
/usr/lib/.../sddm.service 更新
↓
/etc/.../override.conf 保留
↓
systemd 合并两者
所以更安全。
10. 如何查看一个 Unit 最终到底是什么配置?
非常有用:
systemctl cat sshd.service
它会把:
/usr/lib/systemd/system/sshd.service
以及:
/etc/systemd/system/sshd.service.d/*.conf
一起显示出来。
还可以:
systemctl show sshd.service
这个显示的是 systemd 解析后的属性。
比如:
systemctl show sshd.service -p ExecStart
查看最终的:
ExecStart
11. systemctl edit 和 systemctl cat 的关系
可以记成:
systemctl cat
↓
“告诉我这个 Unit 最终由哪些文件组成”
systemctl edit
↓
“我要给这个 Unit 添加一个配置片段”
例如:
systemctl edit sddm.service
产生:
/etc/systemd/system/sddm.service.d/override.conf
然后:
systemctl cat sddm.service
就可以看到:
/usr/lib/systemd/system/sddm.service
/etc/systemd/system/sddm.service.d/override.conf
12. 最后形成一个层次
你可以把 systemd 的配置理解成:
软件包默认配置
│
▼
/usr/lib/systemd/system/*.service
│
│ 被管理员覆盖/扩展
▼
/etc/systemd/system/*.service
│
│ 或
▼
/etc/systemd/system/*.service.d/*.conf
│
▼
systemd 最终配置
其中最值得记住的是:
Unit
↓
一个被 systemd 管理的对象
Unit file
↓
描述这个对象应该如何工作
drop-in
↓
对已有 Unit 做局部修改
/usr/lib/systemd/system
↓
软件包提供的默认 Unit
/etc/systemd/system
↓
管理员配置
*.service.d/*.conf
↓
针对某个 Unit 的配置片段
你以后配置 Arch 时,看到 systemctl edit xxx.service,本质上就是:不要去改软件包提供的原始 Unit,而是在 /etc/systemd/system/xxx.service.d/ 下面增加一个局部配置片段。