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 editsystemctl 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/ 下面增加一个局部配置片段。