摘抄自systemd.unit 中文手册:
http://www.jinbuguo.com/systemd/systemd.unit.html#
对于例如 foo.service
这样的单元文件, 可以同时存在对应的 foo.service.wants/
与 foo.service.requires/
目录, 其中可以放置许多指向其他单元文件的软连接。 软连接所指向的单元将会被隐含的添加到 foo.service
相应的 Wants=
与 Requires=
依赖中。 这样就可以方便的为单元添加依赖关系,而无需修改单元文件本身。 向 .wants/
与 .requires/
目录中添加软连接的首选方法是使用 systemctl(1) 的 enable 命令, 它会读取单元文件的 [Install] 小节(详见后文)
隐含依赖
许多依赖关系是根据单元的类型与设置自动隐含创建的。 这些隐含的依赖关系可以让单元文件的内容更加简洁清爽。 对于各类单元的隐含依赖关系, 可以参考对应手册页的"隐含依赖"小节。
例如,带有 Type=dbus
的 service 单元 将会自动隐含 Requires=dbus.socket
与 After=dbus.socket
依赖。详见 systemd.service(5) 手册。
默认依赖
默认依赖与隐含依赖类似, 不同之处在于默认依赖可以使用 DefaultDependencies=
选项进行开关(默认值 yes
表示开启默认依赖,而设为 no
则表示关闭默认依赖), 而隐含依赖永远有效。 对于各类单元的默认依赖关系, 可以参考对应手册页的"默认依赖"小节。
例如,target 单元将会默认为通过 Wants=
或 Requires=
汇聚的单元 添加 After=
依赖。详见 systemd.target(5) 手册。注意,这个默认行为可以通过 DefaultDependencies=no
关闭。
[Unit] 小节选项
Requires=
设置此单元所必须依赖的其他单元。 当此单元被启动时,所有这里列出的其他单元也必须被启动。 如果此处列出的某个单元启动失败、并且恰好又设置了到这个失败单元的 After=
依赖,那么将不会启动此单元。 想要添加多个单元,可以多次使用此选项,也可以设置一个空格分隔的单元列表。 注意,此选项并不影响单元之间的启动或停止顺序。 要想调整单元之间的启动或停止顺序,请使用 After=
或 Before=
选项。 例如,在 foo.service
中设置了 Requires=bar.service
, 但是并未使用 After=
或 Before=
设定两者的启动顺序, 那么,当需要启动 foo.service
的时候,这两个单元会被并行的同时启动。 建议使用 Wants=
代替 Requires=
来设置单元之间的非致命依赖关系, 从而有助于获得更好的健壮性,特别是在某些单元启动失败的时候。
注意,设置了此依赖并不意味着当本单元处于运行状态时,被依赖的其他单元也必须总是处于运行状态。 例如:(1)失败的条件检查(例如后文的 ConditionPathExists=
,ConditionPathIsSymbolicLink=
, …)只会导致被依赖的单元跳过启动,而不会导致被依赖的单元启动失败(也就是进入"failed"状态)。 (2)某些被依赖的单元可能会自己主动停止(例如有的服务进程可能会主动干净的退出、有的设备可能被用户拔出), 而不会导致本单元自身也跟着一起停止。 要想达到这样的效果,可以同时联合使用 BindsTo=
与 After=
依赖,这样就可以确保:在被依赖的其他单元没有处于运行状态时, 本单元自身永远不会启动成功(详见后文)。
注意, 此种依赖关系也可以在单元文件之外通过向 .requires/
目录中添加软连接来设置。 详见前文。
Requisite=
与 Requires=
类似。 不同之处在于:当单元启动时,这里列出的单元必须已经全部处于启动成功的状态, 否则,将不会启动此单元(也就是直接返回此单元启动失败的消息), 并且同时也不会启动那些尚未成功启动的单元。
Wants=
此选项是 Requires=
的弱化版。 当此单元被启动时,所有这里列出的其他单元只是尽可能被启动。 但是,即使某些单元不存在或者未能启动成功, 也不会影响此单元的启动。 推荐使用此选项来设置单元之间的依赖关系。
注意,此种依赖关系也可以在单元文件之外通过向 .wants/
目录中添加软连接来设置, 详见前文。
BindsTo=
与 Requires=
类似,但是依赖性更强: 如果这里列出的任意一个单元停止运行或者崩溃,那么也会连带导致该单元自身被停止。 这就意味着该单元可能因为 这里列出的任意一个单元的主动退出、某个设备被拔出、某个挂载点被卸载, 而被强行停止。
如果将某个被依赖的单元同时放到 After=
与 BindsTo=
选项中,那么效果将会更加强烈:被依赖的单元必须严格的先于本单元启动成功之后, 本单元才能开始启动。这就意味着,不但在被依赖的单元意外停止时,该单元必须停止, 而且在被依赖的单元由于条件检查失败(例如后文的 ConditionPathExists=
, ConditionPathIsSymbolicLink=
, …)而被跳过时, 该单元也将无法启动。正因为如此,在很多场景下,需要同时使用 BindsTo=
与 After=
选项。
PartOf=
与 Requires=
类似, 不同之处在于:仅作用于单元的停止或重启。 其含义是,当停止或重启这里列出的某个单元时, 也会同时停止或重启该单元自身。 注意,这个依赖是单向的, 该单元自身的停止或重启并不影响这里列出的单元。
Conflicts=
指定单元之间的冲突关系。 接受一个空格分隔的单元列表,表明该单元不能与列表中的任何单元共存, 也就是说:(1)当此单元启动的时候,列表中的所有单元都将被停止; (2)当列表中的某个单元启动的时候,该单元同样也将被停止。 注意,此选项与 After=
和 Before=
选项没有任何关系。
如果两个相互冲突的单元A与B需要在同一个事务内作为B启动, 那么这个事务要么会失败(A与B都是事务中的必要部分[Requires]), 要么就是必须被修改(A与B中至少有一个是事务中的非必要部分)。 在后一种情况下, 将会剔除一个非必要的单元 (若两个都是非必要的单元,则优先剔除A)。
Before=
, After=
强制指定单元之间的先后顺序,接受一个空格分隔的单元列表。 假定 foo.service
单元包含 Before=bar.service
设置, 那么当两个单元都需要启动的时候, bar.service
将会一直延迟到 foo.service
启动完毕之后再启动。 注意,停止顺序与启动顺序正好相反,也就是说, 只有当 bar.service
完全停止后,才会停止 foo.service
单元。 After=
的含义与 Before=
正好相反。 假定 foo.service
单元包含 After=bar.service
设置, 那么当两个单元都需要启动的时候, foo.service
将会一直延迟到 bar.service
启动完毕之后再启动。 注意,停止顺序与启动顺序正好相反,也就是说, 只有当 foo.service
完全停止后,才会停止 bar.service
单元。 注意,此二选项仅用于指定先后顺序, 而与 Requires=
, Wants=
, BindsTo=
这些选项没有任何关系。 不过在实践中也经常遇见将某个单元同时设置到 After=
与 Requires=
选项中的情形。 可以多次使用此二选项,以将多个单元添加到列表中。 假定两个单元之间存在先后顺序(无论谁先谁后),并且一个要停止而另一个要启动,那么永远是"先停止后启动"的顺序。 但如果两个单元之间没有先后顺序,那么它们的停止和启动就都是相互独立的,并且是并行的。 对于不同类型的单元来说,判断启动是否已经完成的标准并不完全相同。 特别的,对于设置在 Before=
/After=
中的服务单元来说, 只有在服务单元内配置的所有启动命令全部都已经被调用,并且对于每一个被调用的命令, 要么确认已经调用失败、要么确认已经成功运行的情况下, 才能认为已经完成启动。
OnFailure=
接受一个空格分隔的单元列表。 当该单元进入失败("failed
")状态时, 将会启动列表中的单元。
[Install] 小节选项
"[Install]
" 小节包含单元的启用信息。 事实上,systemd(1) 在运行时并不使用此小节。 只有 systemctl(1) 的 enable 与 disable 命令在启用/停用单元时才会使用此小节。 注意,"[Install]
" 小节不能出现在单元的 .d/*.conf
配置片段中(参见前文)。 [译者注]"启用"一个单元多数时候在效果上相当于将这个单元设为"开机时自动启动"或"插入某个硬件时自动启动"; "停用"一个单元多数时候在效果上相当于撤销该单元的"开机时自动启动"或"插入某个硬件时自动启动"。
Alias=
启用时使用的别名,可以设为一个空格分隔的别名列表。 每个别名的后缀(也就是单元类型)都必须与该单元自身的后缀相同。 如果多次使用此选项,那么每个选项所设置的别名都会被添加到别名列表中。 在启用此单元时,systemctl enable 命令将会为每个别名创建一个指向该单元文件的软连接。 注意,因为 mount, slice, swap, automount 单元不支持别名,所以不要在这些类型的单元中使用此选项。
WantedBy=
, RequiredBy=
接受一个空格分隔的单元列表, 表示在使用 systemctl enable 启用此单元时, 将会在每个列表单元的 .wants/
或 .requires/
目录中创建一个指向该单元文件的软连接。 这相当于为每个列表中的单元文件添加了 Wants=此单元
或 Requires=此单元
选项。 这样当列表中的任意一个单元启动时,该单元都会被启动。 有关 Wants=
与 Requires=
的详细说明, 参见前面 [Unit] 小节的说明。 如果多次使用此选项,那么每个选项的单元列表都会合并在一起。
在普通的 bar.service
单元内设置 WantedBy=foo.service 选项 与设置 Alias=foo.service.wants/bar.service 选项基本上是等价的。 但是对于模板单元来说,情况则有所不同。 虽然必须使用实例名称调用 systemctl enable 命令, 但是实际上添加到 .wants/
或 .requires/
目录中的软连接, 指向的却是模板单元(因为并不存在真正的实例单元文件)。 假设 getty@.service
文件中存在 WantedBy=getty.target 选项, 那么 systemctl enable getty@tty2.service 命令 将会创建指向 getty@.service
的软连接 getty.target.wants/getty@tty2.service
Also=
设置此单元的附属单元,可以设为一个空格分隔的单元列表。 表示当使用 systemctl enable 启用 或 systemctl disable 停用 此单元时, 也同时自动的启用或停用附属单元。
如果多次使用此选项, 那么每个选项所设置的附属单元列表都会合并在一起。