Systemd 单元文件介绍
文件路径与名字
在开始编写配置文件前,我们需要先了解一下一些设定.
文件存放路径
Systemd 从一下地方读取配置文件:
- /usr/lib/systemd/system/: 存放绝大部分配置文件.
- /etc/systemd/system/: systemd 启动时会默认执行的路径.
- /usr/lib/sysemd/user/:
- ~/.local/share/systemd/user/
- /etc/systemd/system/user:
- ~/.config/systemd/user/
名字约定
配置文件名字只能由 ASCII 字母,下划线和点组成.
末尾带有 @的是模板服务,子服务通过在 @后添加内容作为值, 将模板服务实例化。在模板中 代表那个值的字符为 % i.
编辑文件的道道
因为包配置文件会经常更新,所以直接修改包文件是个很蠢的办法.
为了能一劳永逸地完成修改,我们有两种方式:
- 在另一个地方覆盖原来的文件
使用systemctl edit --full
在 /etc/systemd/system/ 中创建或打开对应的配置文件. 如果设置了默认启动, 修改完后使用systemctl reenable
重新链接新文件. - 使用附加文件。它们会附加到原文件的首部.
使用
systemctl edit
编辑完后,相关服务必须重启才能让修改生效.
如果通过 systemctl edit
修改,服务会自 动重启.
或者直接粗暴一点,
systemctl daemon-reload
重启所有单元.
提示:
- 可以利用
systemd-delta
查看所有被覆盖和修改过的文件. - 可以使用
systemctl cat
查看附加了附加文件的配置文件.
配置文件的编写
Unit
描述: Description
定义这个服务的综合描述.
文档: Documentation
定义文档的位置,如 man:sshd(8) man:sshd_config(5)
.
依赖: Wants 和 Requires
Sytemd 提供 2 种引入依赖的方式:
Wants=
所依赖的服务名:这种依赖是可选的, 即使所依赖的服务启动失败,父服务 也应该能正常执行.Requires=
所依赖的服务名:这种依赖是强制的.
执行顺序: After 与 Before
注意,上面两种语句都不会强制要求子服务在父服务之前启动,
要强制做到这一点,请使用 after=要先启动的服务
.
否则,这些服务可能干脆并行启动.
相应地还有一个 Before 变量定义该服务在哪些服务前启动.
多个服务间用空格简单分开就好.
冲突避免: Conflicts
定义会与该服务冲突的服务 (组), 当变量里的服务 (组) 在运行时, 该服务不能运行.
Service
环境变量文件: EnvironmentFile
定义当前服务的环境参数文件路径.
参数文件采用键=值
的格式.
可以用 $键
在配置文件中引用.
服务类型: Type
Systemd 提供多种类型的服务满足不同场景下的使用.
服务类型通过 Service 一节的变量 Type
决定:
- simple: 默认值. Systemd 会立刻启动该服务.
ExecStart 在主进程中执行命令. 如果需要使用别的服务,
不要用这个类型.
- idle: 基本同 simple, 只是 systemd 会在其他服务都被调度妥当后才会执行. 一种场合是要让该服务的输出与其它服务分离开来.
- notify: 基本与 simple 相同。只是服务保证会适时地向 systemd 发信号.
- dbug: 类似 simple, 但是会等待 DBus 信号后启动.
- forking: ExecStart 变量将会以分支进程的形式执行.
- oneshot: 执行无死循环的程序并马上退出.
执行命令: Exec*
这个变量家族决定在什么时候执行什么样的命令, 在赋值符号后加一个 "-" 可以关闭错误输 出.
- ExecStart: 启动服务时执行的命令.
- ExecReload: 重启服务时执行的命令.
- ExecStop: 停止服务时执行的命令.
- ExecStartPre: 启动服务前执行的命令.
- ExecStartPost: 启动服务后执行的命令.
- ExecStopPost: 停止服务后执行的命令.
终结方式: KillMode
定义 Systemd 如何停止服务.
- control-group: 杀死当前控制组里的所有进程.
- process: 只杀死主进程. 经常被 sshd 等不希望停止服务后连接全断的服务使用.
- mixed: 主进程收到 SIGTREM, 子进程收到 SIGKILL.
- none: 执行 ExecStop
重启相关: Restart (Sec)
Restart
定义退出后的重启方式.
RestartSec
定义重启前等待的秒数.
- no: 不重启
- on-success: 仅在正常退出后重启.
- on-failure: 仅在异常退出后重启。守护进程常用.
- on-adnormal: 仅在收到终止信号或超时后才重启.
- on-abort: 仅在被未捕获信号终止后重启.
- on-watchdog: 仅在超时退出后重启.
- always: 总是重启.
执行者: User 和 Group
Install
划定服务组: WantedBy
定义该服务所在的服务组.
服务组
服务组表示一组服务,
服务组有单独的文件。配置上基本与服务无异。后缀名是 target.
利用 systemd get-default
可以查看默认启动的服务组.
利用 systemctl list-dependencies
可以查看某个服务或服务组的包含的服务.
利用 systemctl isolate
可以切换到另一个服务组.
常用的服务组为 multi-user.target 和 graphical.target, 后者依赖前者.
定时器
就像服务组一样,定时器也有自己的文件。后缀名是 timer.
文件配置也基本与普通服务相同。最大的不同是多了一节 Timer.
定时器的文件名字最好与一个已经存在服务的文件名字相同,
代表这个定时器管理那个服务。当然,
我们也可以在 timer 一节中添加 Unit
变量指定一个名字不同的服务.
被管理的服务这下就不需要 Install 了,因为定时器会帮它照料好.
概括说来,有两种定时器: + 实时定时器:
使用变量 OnCalendar
. 在某一特定日期触发.
格式为 DayOfWeek Year-Month-Day Hour:Minute:Second, "*" 代表任意值,
用 "上界.. 下界" 代表一个区间,用 "," 连接多个可能值.
当然,大家都懒,像 "daily", "weekly" 这样的简写也可以用.
想要知道自己时间究竟写对没有了吗?
运行 systemd-analyze calendar 时间
就可以知道下次
触发的时间了.
定时器只会在它启动的状态下触发。要是该触发的时候没有启动,
那么这次触发就丢失了。将 Persistent
变量赋值为真,
定时器在下次启动时就会补上遗漏的触发. + 单调定时器:
使用变量家族 On类型Sec
, 在某时间发生了一个时间段后触发.
电脑关机 或休眠的时间不计入.
类型可以是: + Boot + UnitActive + StartUp + Active + UnitInactive
要是担心多个任务同时唤醒会使得系统一下子变得很卡,
RandomizeDelaySec
可以在预订
时间上加一个不超过所给值的延迟.
临时定时器
除了大动干戈的创建两个文件, systemd 事实上提供了一种更为方便的临时定时器.
systemd-run --on-active="时间点或时间段" 命令及参数......
systemd-run --on-active="时间点或时间段" --unit 服务名
以上两种方式会临时性的创建一个定时器运行命令或服务.