首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用OnFailure=和Restart=混淆系统行为

用OnFailure=和Restart=混淆系统行为
EN

Unix & Linux用户
提问于 2018-02-08 23:50:45
回答 1查看 13.8K关注 0票数 9

我在嵌入式系统中使用systemd 231,我试图创建一个服务来监视系统中的硬件组件。以下是我试图做的事情的粗略描述:

  1. 当服务foo.service启动时,它会启动一个应用程序foo_app
  2. foo_app监控硬件组件,连续运行。
  3. 如果foo_app检测到硬件故障,它将退出,返回代码为1。这将触发系统重新启动。
  4. 如果foo_app崩溃,systemd应该重新启动foo_app
  5. 如果foo_app一再崩溃,systemd应该重新启动系统。

下面是我将其实现为服务的尝试:

代码语言:javascript
复制
[Unit]
Description=Foo Hardware Monitor

# If the application fails 3 times in 30 seconds, something has gone wrong,
# and the state of the hardware can't be guaranteed. Reboot the system here.
StartLimitBurst=3
StartLimitIntervalSec=30
StartLimitAction=reboot

# StartLimitAction=reboot will reboot the box if the app fails repeatedly,
# but if the app exits voluntarily, the reboot should trigger immediately
OnFailure=systemd-reboot.service

[Service]
ExecStart=/usr/bin/foo_app

# If the app fails from an abnormal condition (e.g. crash), try to
# restart it (within the limits of StartLimit*).
Restart=on-abnormal

从文档(systemd.servicesystemd.service)来看,如果我以触发Restart=on-abnormal (例如killall -9 foo_app)的方式杀死foo_app,系统d应该优先于OnFailure=systemd-reboot.service而不是启动systemd-reboot.service

然而,这不是我所看到的。一旦我杀死foo_app一次,系统就会立即重新启动。

下面是一些来自文档的相关片段:

OnFailure=:当该单元进入“失败”状态时激活的一个或多个单元的空格分隔列表。只有在达到开始限制之后,使用Restart=的服务单元才进入失败状态。Restart=注意到,服务重新启动受制于使用StartLimitIntervalSec=和StartLimitBurst=配置的单元启动速率限制,有关详细信息,请参阅systemd.unit(5)。重新启动的服务只有在达到开始限制后才进入失败状态。

这些文档似乎相当清晰:

  • OnFailure中指定的服务只应在服务进入"failed“状态时才运行。
  • 服务只有在满足failedStartLimitIntervalSec之后才能进入“StartLimitBurst”状态。

这不是我看到的。

为了确认这一点,我将服务文件编辑为:

代码语言:javascript
复制
[Unit]
Description=Foo Hardware Monitor  
  
StartLimitBurst=3
StartLimitIntervalSec=30
StartLimitAction=none

[Service]
ExecStart=/usr/bin/foo_app
Restart=on-abnormal

通过删除OnFailure和设置StartLimitAction=none,我能够看到systemd是如何响应foo_app死亡的。这里有一个测试,在这个测试中,我反复使用SIGKILL杀死D49

代码语言:javascript
复制
[root@device ~]
# systemctl start foo.service
[root@device ~]
# journalctl -f -o cat -u foo.service &
[1] 2107
Started Foo Hardware Monitor.
[root@device ~]
# killall -9 foo_app
foo.service: Main process exited, code=killed, status=9/KILL
foo.service: Unit entered failed state.
foo.service: Failed with result 'signal'
foo.service: Service hold-off time over, scheduling restart.
Stopped foo.
Started foo.

[root@device ~]
# killall -9 foo_app
foo.service: Main process exited, code=killed, status=9/KILL
foo.service: Unit entered failed state.
foo.service: Failed with result 'signal'
foo.service: Service hold-off time over, scheduling restart.
Stopped foo.
Started foo.

[root@device ~]
# killall -9 foo_app
foo.service: Main process exited, code=killed, status=9/KILL
foo.service: Unit entered failed state.
foo.service: Failed with result 'signal'
foo.service: Service hold-off time over, scheduling restart.
Stopped foo.
foo.service: Start request repeated too quickly
Failed to start foo.
foo.service: Unit entered failed state.
foo.service: Failed with result 'start-limit-hit'

这在很大程度上是有道理的。当foo_app被杀死时,systemd会重新启动它,直到StartLimitBurst被击中,然后放弃。这是我想要的,除了StartLimitAction=reboot

不寻常的是,每当foo.service: Unit entered failed state.被杀死时,systemd都会打印foo_app,即使它即将通过Restart=on-abnormal重新启动。这似乎直接与上面引用的文档中的这些行相矛盾:

只有在达到开始限制之后,使用Restart=的服务单元才进入失败状态。重新启动的服务只有在达到开始限制后才进入失败状态。

所有这些都让我很困惑。我是否误解了这些系统的选择?这是系统缺陷吗?任何帮助都是非常感谢的。

EN

回答 1

Unix & Linux用户

回答已采纳

发布于 2018-03-28 20:23:22

Edit 2019/08/12:根据therealjumbo's的注释,修复程序已经与systemd v239合并并发布,因此,如果您由于发行版(查看CentOS)而没有被固定在某个版本上,那么更新并使其愉快!

DR;DR文档问题,目前仍然是systemd项目的一个悬而未决的问题。

事实证明,自从您提出这个问题以来,这个问题在文档和实际行为之间已经在systemd中得到了报告和D4。根据我的理解(以及我对github问题的解读),您的期望和文档匹配,所以您没有疯。

当前,无论是否已达到启动限制,systemd都会在每次尝试启动后将状态设置为失败。在这个问题上,OP写了一个有趣的关于学习骑自行车的趣闻轶事,我强烈建议你好好看看。

票数 10
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/422933

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档