Systemd Restart=always 不兑现

Ben*_*rel 89 systemd

注意:我在 Medium 上写了一篇文章,解释了如何创建服务,以及如何避免这个特定问题:Creating a Linux service with systemd

原问题:


我正在使用 systemd 来保持工作脚本始终工作:

[Unit]
Description=My worker
After=mysqld.service

[Service]
Type=simple
Restart=always
ExecStart=/path/to/script

[Install]
WantedBy=multi-user.target
Run Code Online (Sandbox Code Playgroud)

虽然如果脚本在几分钟后正常退出,重启工作正常,但我注意到如果它在启动时反复执行失败,systemd将放弃尝试启动它:

Jun 14 11:10:31 localhost systemd[1]: test.service: Main process exited, code=exited, status=1/FAILURE
Jun 14 11:10:31 localhost systemd[1]: test.service: Unit entered failed state.
Jun 14 11:10:31 localhost systemd[1]: test.service: Failed with result 'exit-code'.
Jun 14 11:10:31 localhost systemd[1]: test.service: Service hold-off time over, scheduling restart.
Jun 14 11:10:31 localhost systemd[1]: test.service: Start request repeated too quickly.
Jun 14 11:10:31 localhost systemd[1]: Failed to start My worker.
Jun 14 11:10:31 localhost systemd[1]: test.service: Unit entered failed state.
Jun 14 11:10:31 localhost systemd[1]: test.service: Failed with result 'start-limit'.
Run Code Online (Sandbox Code Playgroud)

同样,如果我的工作脚本多次失败并退出状态为255systemd则放弃尝试重新启动它:

Jun 14 11:25:51 localhost systemd[1]: test.service: Failed with result 'exit-code'.  
Jun 14 11:25:51 localhost systemd[1]: test.service: Service hold-off time over, scheduling restart.  
Jun 14 11:25:51 localhost systemd[1]: test.service: Start request repeated too quickly.  
Jun 14 11:25:51 localhost systemd[1]: Failed to start My worker.  
Jun 14 11:25:51 localhost systemd[1]: test.service: Unit entered failed state.  
Jun 14 11:25:51 localhost systemd[1]: test.service: Failed with result 'start-limit'.
Run Code Online (Sandbox Code Playgroud)

有没有办法强制systemd总是在几秒钟后重试吗?

小智 88

我想稍微扩展一下 Rahul 的回答。

systemd 尝试重新启动多次 ( StartLimitBurst) 并在StartLimitIntervalSec. 这两个选项都属于该[unit]部分。

执行之间的默认延迟为 100 毫秒 ( RestartSec),这会导致非常快地达到速率限制。

对于定义重启策略的单元,systemd 不会再尝试自动重启:

请注意,已配置Restart=并达到启动限制的单元不再尝试重新启动;然而,它们仍可能在稍后手动重启,从那时起,重启逻辑再次被激活。

Rahul 的回答有帮助,因为较长的延迟会阻止在StartLimitIntervalSec时间内到达错误计数器。正确的答案是同时设置RestartSecStartLimitBurst设置合理的值。

  • 现在我(终于)明白它是如何工作的,经过一些反复试验,我可以看到你的答案是最正确的。我的底线是:设置`StartLimitIntervalSec=0`,瞧。 (10认同)

Rah*_*hul 59

是的,有。您可以x[Service]部分下指定秒后重试,

[Service]
Type=simple
Restart=always
RestartSec=3
ExecStart=/path/to/script
Run Code Online (Sandbox Code Playgroud)

保存文件后,您需要重新加载守护程序配置以确保systemd知道新文件,

systemctl daemon-reload
Run Code Online (Sandbox Code Playgroud)

然后重新启动服务以启用更改,

systemctl restart test
Run Code Online (Sandbox Code Playgroud)

根据您的要求,查看文档,

Restart=on-failure
Run Code Online (Sandbox Code Playgroud)

听起来是一个不错的建议。

  • 根据 [doc](https://www.freedesktop.org/software/systemd/man/systemd.service.html#Restart=) 判断,`always` 是 `on-failure` 的超集,所以它不会'没有帮助! (4认同)

Jde*_*eBP 6

systemd 放弃尝试重新启动它

第systemd放弃尝试重新启动了一小会儿。这清楚地显示在您提供的日志中:

6 月 14 日 11:25:51 localhost systemd[1]: test.service: Failed with result 'start-limit'

这是速率限制启动。

使用StartLimitIntervalSec=设置在服务单元中指定了一小段时间的长度。通过StartLimitBurst=设置指定在该间隔内触发速率限制机制所需的启动次数。如果您的系统上没有与 vanilla systemd 不同的东西,包括这两个设置的默认值,那么它在 10 秒内是 5 次。

StartLimitIntervalSec=0禁用速率限制,因此 systemd 将永远重试而不是放弃。但是,让您的服务要么不经常退出,要么在退出和重新启动之间足够空闲以使其不超过速率限制阈值,这是更好的方法。

请注意,速率限制并不关心您的服务是如何退出的。它会根据尝试启动/重新启动它的次数而触发,无论其原因如何。

进一步阅读

  • 不过,它似乎确实永久放弃了:“自 2016 年 6 月 15 日星期三 CEST;12 小时前,活动:失败(结果:开始限制)”。它保持在这种状态并且脚本永远不会再次执行。我尝试手动设置 `StartLimitIntervalSec=10` 和 `StartLimitIntervalSec=5`,没有运气。 (8认同)
  • 默认情况下,它确实会永久放弃。请参阅 https://github.com/systemd/systemd/issues/2416。 (8认同)
  • 底线:要阻止它永久放弃,请设置“StartLimitIntervalSec=0”。 (5认同)