如果你的服务处于不应该被终止的状态,让 systemd 不会终止它

如果你的服务处于不应该被终止的状态,让 systemd 不会终止它

我有一个关于 systemd 服务配置的问题。

服务应用程序是控制机器的应用程序。在应用程序中,SIGINT、SIGTERM、SIGQUIT 和 SIGHUP 被捕获。当机器处于“运行”状态时,这些信号将被忽略并且应用程序不会退出。如果机器处于“已停止”模式,则退出控制应用程序。

我们希望与 Linux 一起启动该应用程序,因此我们将该应用程序添加为 systemd 服务。

到目前为止我们有以下配置:

[Unit]
Description=Machine control service
After=network.target

[Service]
Type=simple
User=simplemachine
Group=simplemachine
CPUSchedulingPolicy=other
LimitRTPRIO=80
LimitRTTIME=infinity

WorkingDirectory=/opt/simplemachine/bin/
ExecStart=/opt/simplemachine/bin/simplemachine
KillMode=none
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

现在我有以下问题。当我执行时:

sudo systemctl stop machine.service

我希望 systemctl 发送一个 SIGTERM,这样应用程序只有在允许停止时才会停止。当应用程序不停止时也是如此。如果 systemctl 不会终止进程就好了,但是例如返回某种错误或超时代码,这意味着它可能不会停止进程。

如何使用新的 systemd 系统实现这一目标?

答案1

这个答案主要基于以下文档systemd.kill,但在做了一些测试后已更新。诚然,这并不是这个问题的完美解决方案。

通过设置SendSIGKILL=no在您的单元文件中,可以防止进程被终止。要允许SIGTERM发送首字母,您可能需要将该KillMode选项恢复为其默认值,即control-group

通过这些设置,运行systemctl stop machine.service应该像这样:

  1. ExecStop=由于单元文件中没有指定命令,因此SIGTERM将 a 发送到进程。

  2. 90 秒后 ( DefaultTimeoutStopSec),systemd考虑强制终止该进程。

  3. 因为SendSIGKILL设置为no,所以SIGKILL( FinalKillSignal) 是不是发送到进程,进程继续运行。

实际上,发送到进程的唯一信号systemctl stop将是SIGTERM。由于 的处理SIGTERM是在应用程序本身内处理的,因此systemctl stop应该按预期工作:当远程计算机关闭时停止应用程序,当远程计算机启动时超时。

Michał Politowski 在评论中指出了这种方法的问题。即,systemd一旦停止超时到期,将认为该单元发生故障。这不会影响进程本身,但会改变 systemd 对进程的看法。如果您在设备处于此状态时发出另一个“systemctl start”命令,您将最终得到两个进程。

您已经使用的选项KillMode=none完全避免了进程终止逻辑。然而,结果与此方法类似。单元的状​​态更改为非活动状态,而进程继续运行。

作为补充说明,90 秒超时可以配置为TimeoutStopSec

相关内容