绑定服务的 Systemd 计时器重新启动它绑定的服务

Systemd timer for a bound service restarts the service it is bound to

我有两个系统服务 ab,其中 b 是 "After" 和 "BindsTo" ab 是一个简短的命令,每分钟使用 systemd 计时器启动一次。

这是我的配置:

$ cat /systemd/a.service
[Unit]
After=foo
BindsTo=foo

[Service]
ExecStart=/opt/a/bin/a
Group=lev
User=lev
Restart=Always
WorkingDirectory=/opt/a

$ cat /systemd/b.service
[Unit]
After=a
BindsTo=a

[Service]
ExecStart=/opt/b/bin/b
Group=lev
User=lev
WorkingDirectory=/opt/b

$ cat /systemd/b.timer
[Unit]

[Timer]
OnCalendar=*:0/1:00

当我 运行 sudo systemctl stop a 时,服务 a 确实停止了,但是当服务计时器 [=12] 的下一分钟开始时它又重新启动=] 运行s b

systemd 文档指出 BindsTo

declares that if the unit bound to is stopped, this unit will be stopped too.

(https://www.freedesktop.org/software/systemd/man/systemd.unit.html#BindsTo=)

我希望通过停止 ab 也会停止,并且计时器会被禁用。不是这种情况。你能帮忙解释一下为什么 b 计时器不仅会重新启动 b(应该会失败),还会重新启动 a 吗?

你也能帮我编辑这些服务吗:

提前致谢!

我可能弄错了,但我相信“Restart=Always”选项是名为 a 的服务启动的原因,因此名为 b 的服务随后没有停止的原因。

systemd.service 的手册页说明了此选项是否设置为始终

the service will be restarted regardless of whether it exited cleanly or not, got terminated abnormally by a signal, or hit a timeout.

https://www.freedesktop.org/software/systemd/man/systemd.service.html#Restart=

因此,即使您正在停止服务,此选项也会重新启动它。

您可以通过运行执行以下命令来测试它。由于您在一分钟计时器上有服务“b”,我会 运行 在一分钟结束后 10 秒停止命令(即 10:00:10)。然后我会在20秒后运行状态命令,看看服务是否已经重启。

sudo systemctl 停止一个 sudo systemctl status a b

以下是满足您的限制的最简单的单位:

test-a.service

[Service]              
ExecStart=sleep 3600  # long-running command

test-b.service

[Service]     
ExecStart=date  # short command

test-b.timer

[Unit]                                
After=test-a.service
BindsTo=test-a.service   # makes test-b.timer stop when test-a.service stops
                                      
[Timer]                                           
OnCalendar=* *-*-* *:*:00             
                                      
[Install]                             
WantedBy=test-a.service  # makes test-b.timer start when test-a.service starts

别忘了

  • systemctl daemon-reload
  • systemctl disable test-b.timer
  • systemctl enable test-b.timer 应用 [Install] 部分中的更改。

解释:

  • 你想要的是将 a.service 绑定到 b.timer,而不是 b.service
  • b.service只是一个短命令,systemctl start b.service只会运行这个命令,不会启动相关的定时器
  • 只有systemctl start b.timer会启动计时器
  • WantedBy 告诉 systemd 在 test-a.service 启动时启动 test-b.timer
  • BindsTo 告诉 test-b.timer 在 test-a.service 停止时停止
  • After 仅确保 test-b.timer 不会与 test-a.service 同时启动:它将强制 systemd 在 test-b.timer 之后启动 test-a.service 已完成启动。

关于您观察到的行为:

  • 当您停止 a.service 时,b.timer 仍然处于活动状态并且它尝试从 b.service 开始到 运行 它的短命令。由于您的 b.service 指定了 BindsTo=a.service,systemd 认为 b.service 也需要 a.service 启动,并且有效地重新启动了 a.service for b.service to 运行正确。