我正在尝试在systemd
单元文件中描述的两个服务之间创建依赖关系:
- a.service 必须在 b.service 之前启动
- 如果a.service失败则b.service无法启动
这是我所拥有的:
% cat a.service
[Unit]
Description=A-Service
Before=b.service
[Service]
ExecStart=/opt/a.sh
[Install]
WantedBy=multi-user.target
% cat b.service
[Unit]
Description=B-Service
After=a.service
[Service]
ExecStart=/opt/b.sh
[Install]
WantedBy=multi-user.target
这是为服务 A 和 B 执行的简单脚本:
% cat a.sh
#!/bin/sh
echo "A service started"
exit 0
% cat b.sh
#!/bin/sh
echo "B service started"
while [ true ]; do
sleep 1
do
exit 0
因此,我尝试通过从 返回exit 1
来模拟/服务失败a.sh
,systemctl status a.service
将其报告为失败:
Active: failed (Result: exit-code) ...
Process: 843 ExecStart=/opt/a.sh (code=exited, status=1/FAILURE)
...
但是 b.service 仍然启动并处于活动状态:
% systemctl status b.service
...
Active: active (running) ...
Process: 844 ExecStart=/opt/b.sh (code=exited, status=0/SUCCESS)
...
此外,b.service 依赖项确实包含 a.service(状态为“失败”):
% systemctl list-dependencies b.service
...
我究竟做错了什么?是脚本有问题还是[Unit]定义不完整?
答案1
我会用一个Requires
第二单元的属性:
如果该单位被激活,列出的单位也将被激活。如果其他单元之一无法激活,并且设置了对失败单元的排序依赖性 After=,则该单元将不会启动。
我还更改了要分叉的每个单元的类型,因为默认类型“简单”将认为该单元在 shell 启动后启动,而分叉单元将等待 shell 退出。此类型更改在此仅对于 A-Service 至关重要。
我还Before=b.service
从 A-Service 中删除了,因为从 B 到 A 的向后依赖(使用 B 的“After”指令)对我来说更有意义,而且您不必两者都拥有。
生成的单元文件是:
[Unit]
Description=A-Service
[Service]
Type=forking
ExecStart=/opt/a.sh
[Install]
WantedBy=multi-user.target
和:
[Unit]
Description=B-Service
Requires=a.service
After=a.service
[Service]
Type=forking
ExecStart=/opt/b.sh
[Install]
WantedBy=multi-user.target