在systemd.unit(5)中,选项Requires=意味着:
配置其他单元上的需求依赖项。如果这个单位被激活,这里列出的单位也将被激活。如果其他单元中的一个被停用或激活失败,则此单元将被停用。
我做了个小实验。我创建了两个服务:a.service和b.service:
# cat a.service
[Service]
ExecStart=/bin/false
# cat b.service
[Unit]
Requires=a.service
[Service]
ExecStart=/bin/sleep 1000在我做完
systemctl start b.service
我预计a.service和b.service都会失败,因为a.service失败了/bin/false,b.service失败了a.service失败了。
但是,b.service正在运行:
root@john-ubuntu:/etc/systemd/system# systemctl status a.service b.service
● a.service
Loaded: loaded (/etc/systemd/system/a.service; static; vendor preset: enabled)
Active: failed (Result: exit-code) since Thu 2017-09-07 16:38:39 CST; 2s ago
Process: 1245 ExecStart=/bin/false (code=exited, status=1/FAILURE)
Main PID: 1245 (code=exited, status=1/FAILURE)
Sep 07 16:38:39 john-ubuntu systemd[1]: Started a.service.
Sep 07 16:38:39 john-ubuntu systemd[1]: a.service: Main process exited, code=exited, status=1/FAILURE
Sep 07 16:38:39 john-ubuntu systemd[1]: a.service: Unit entered failed state.
Sep 07 16:38:39 john-ubuntu systemd[1]: a.service: Failed with result 'exit-code'.
● b.service
Loaded: loaded (/etc/systemd/system/b.service; static; vendor preset: enabled)
Active: active (running) since Thu 2017-09-07 16:38:39 CST; 2s ago
Main PID: 1244 (sleep)
Tasks: 1
Memory: 88.0K
CPU: 696us
CGroup: /system.slice/b.service
└─1244 /bin/sleep 1000
Sep 07 16:38:39 john-ubuntu systemd[1]: Started b.service.我错过了什么吗?谢谢。
发布于 2017-09-07 21:45:59
这很棘手。要理解的主要问题是,除非被告知不能并行启动,否则systemd将并行启动所有东西。这实际上在“要求”一节的手册页中有说明:
需求依赖关系不影响服务启动或停止的顺序。
您想要实现的是“在启动a.service之前等待启动b.service”。为此,您需要b.service文件中的"Requires“和"After”选项:
[Unit]
Requires=a.service
After=a.service
[Service]
ExecStart=/bin/sleep 1000=更新=
好的,我看到了问题所在:在您的a.service文件中,您放置了ExecStart命令,没有指定类型。这意味着Type将默认为'Simple‘。你需要那种“叉子”才能让它起作用。来自systemd.service手册页:
如果设置为simple (如果没有指定Type=或BusName=,而是指定了ExecStart= ),那么使用ExecStart=配置的进程将是服务的主要进程。在这种模式下,如果进程向系统上的其他进程提供功能,则应该在启动守护进程之前安装其通信通道(例如,由systemd通过套接字激活建立套接字),因为systemd将立即启动后续单元。如果设置为分叉,则使用ExecStart=配置的进程将调用fork()作为其启动过程的一部分。当启动完成并设置所有通信通道时,预期父进程将退出。子进程继续作为主守护进程运行。这是传统UNIX守护进程的行为。如果使用此设置,建议也使用PIDFile=选项,以便systemd能够识别守护进程的主要进程。系统d将在父进程退出后立即启动后续单元。
因此,您应该更新您的a.service文件以包含'Type=Forking':
[Service]
Type=forking
ExecStart=/bin/false这会管用的。:)
发布于 2018-07-25 06:43:05
如果使用systemd-219的CentOS 7(它的systemd.unit(5)手册页与问题中引用的部分匹配),这可能部分是由于文档错误造成的。也许对其他发行版和systemd版本也是如此。
评论中引用的这句话:
如果其他单元中的一个被停用或激活失败,则此单元将被停用。
我认为systemctl start b.service会导致这两个服务都被激活,但是在a.service从/bin/false返回失败后,b.service将自动停用。正如问题中所说的,这不是观察到的行为,我没有在CentOS 7上观察到这种行为。
在https://www.freedesktop.org/software/systemd/man/systemd.unit.html,引用的句子被以下句子所取代:
如果其他单元中的一个无法激活,并且设置了故障单元上的顺序依赖项After=,则该单元将不会启动。此外,无论是否指定了After=,如果显式停止了其他单元之一,则将停止此单元。
更新后的文档与@gerard的声明一致,即您需要在After=中设置b.service,并与我在CentOS 7上观察到的行为相匹配。
然后,正如@gerard所说,当systemd启动一个Type=simple服务时,它“将立即启动后续单元”。请注意,Type=forking不是唯一可用于解决此问题的设置,您还可以设置Type=notify或systemd.service(5)手册页中描述的其他类型之一(Type=idle除外)。当您已经过了测试失败处理阶段时,请确保该服务在其Type (例如,它调用fork()、sd_notify()等)时实际按需要运行。
还请注意,在systemd-219中,在故障处理方面有很多边缘情况,例如https://github.com/systemd/systemd/issues/8398。
https://unix.stackexchange.com/questions/390898
复制相似问题