背景

背景

背景

我被要求systemd为新服务创建一个脚本,foo_daemon该服务有时会进入“不良状态”,并且不会通过SIGTERM(可能是由于自定义信号处理程序)终止。这对开发人员来说是个问题,因为他们被指示通过以下方式启动/停止/重新启动服务:

  • systemctl start foo_daemon.service
  • systemctl stop foo_daemon.service
  • systemctl restart foo_daemon.service

问题

有时,由于foo_daemon陷入不良状态,我们必须通过以下方式强制终止它:

  • systemctl kill -s KILL foo_daemon.service

问题

如何设置我的systemd脚本以便foo_daemon每当用户尝试停止/重新启动服务时,systemd都会:

  • foo_daemon尝试通过正常关闭SIGTERM
  • 等待最多 2 秒钟以foo_daemon完成关闭/终止。
  • 如果进程仍然存在,则尝试强制关闭foo_daemonvia (这样我们就不会面临 PID 被回收和针对错误 PID发出问题的风险)。我们正在测试的设备会快速生成/分叉大量进程,SIGKILLsystemdSIGKILL因此,人们确实担心 PID 循环会导致问题。
  • 如果在实践中,我只是对 PID 回收感到偏执,那么我同意脚本只SIGKILL针对进程的 PID 发出指令,而不必担心终止回收的 PID。

答案1

systemd 已经支持此功能,并且默认启用

您可能想要自定义的唯一内容是超时,您可以使用 来执行此操作TimeoutStopSec=。例如:

[Service]
TimeoutStopSec=2

现在,systemd 将发送一个 SIGTERM,等待两秒钟让服务退出,如果没有,它将发送一个 SIGKILL。

如果您的服务不支持 systemd,您可能需要提供其 PID 文件的路径PIDFile=

最后,您提到您的守护进程会生成许多进程。在这种情况下,您可能希望设置KillMode=control-group,然后 systemd 将向 cgroup 中的所有进程发送信号。

答案2

由于没有人提到需要Type=oneshot,这里有一个由于超时失败而退出的完整示例。

[Unit]
Description=timeout test

[Service]
Type=oneshot
TimeoutStartSec=2
ExecStart=/bin/sleep 10

相关内容