我们的看门狗重启了我们有意停止的服务
运维
我们的一个看门狗会启动任何已启用但未运行的服务。十月份有两次,它启动了我们有意停止的服务。第二次,我们其中一个网站的访客遇到了大约 45 分钟的错误。
为什么需要这个看门狗
例如,一个在收到 SIGTERM 时干净退出的服务,比如因为某个进程按名称杀死了它,在 systemd 看来并不是“失败”的。Restart=on-failure 不会将其重启,systemctl --failed 也不会列出它。它会一直保持停止状态,直到有人碰巧注意到。因此,看门狗会查找已启用但未运行的服务,并启动它们。
问题在于,手动停止的服务看起来与故障服务完全一样。
第一次
10 月 7 日,我们在 12:47 使用 systemctl stop 停止了一个视频工作进程,以便编辑其作业队列。12:55 时它又运行了:看门狗启动了它。
第二次
10 月 21 日,我们需要那台同时为两个网站提供服务的机器的内存来进行模型测试。一个脚本使用 systemctl stop 停止了网站的 Web 应用、一个同步作业和一个数据库容器。大约五分钟后,一个监视网站的定时器,以及在 19:14 的看门狗,将隧道和 Web 应用重新启动了。
隧道重新接收流量,但 Web 应用无法响应:正在测试的模型占用了机器 114 GiB 的内存。从大约 19:14 到 20:00,部分访客遇到了 502 错误。20:00 时,我们禁用了隧道、Web 应用和同步作业,并停止了监视定时器。
我们现在使用的规则
- 通过禁用服务来暂停它:
sudo systemctl disable --now <unit>。使用sudo systemctl enable --now <unit>将其恢复。我们的看门狗只检查已启用的服务,因此被禁用的服务不会受到干扰。 - 暂停所有可能将其恢复的项目:它前面的隧道以及任何监视它的定时器。
- 短暂停止是一场竞态。 如果您只使用
stop,请在下次检查之前完成操作,而在我们的机器上,检查间隔仅为几分钟。
同月份遇到的另外两个 systemd 陷阱
- 对于
/etc/systemd/system中的单元文件,systemctl mask --runtime不起作用。/etc中的单元优先于/run中的运行时掩码,因此命令执行成功但服务仍然启动。为了保持服务停止状态,我们使用带有ConditionPathExists=!/etc/<name>.hold的 drop-in 文件:只要该文件存在,服务就不会启动,无论是开机时还是手动启动。 systemctl is-active将正在运行的 oneshot 服务报告为非活动状态。 当Type=oneshot服务运行时,其状态为 "activating",因此is-active会打印该状态并返回 3。像while systemctl is-active --quiet job.service; do sleep 60; done这样旨在等待夜间任务的循环会立即退出。请改为读取状态:active、activating、reloading 或 deactivating 均表示服务仍在运行。
Factory Floor 监控已启用但未运行的服务。默认情况下,它仅报告这些服务,只有当您开启相应选项时才会启动它们。自 1.0.3 版本起,其警报还会说明如何有意暂停服务,其运维手册也包含了相同内容。