如果您的服务处于不应被杀死的状态,请让 systemd 不杀死它

Jan*_*aap 7 linux systemd systemctl

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

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

我们想和 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
Run Code Online (Sandbox Code Playgroud)

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

sudo systemctl stop machine.service
Run Code Online (Sandbox Code Playgroud)

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

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

Hax*_*iel 5

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

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

使用这些设置,运行systemctl stop machine.service应该是这样的:

  1. 因为ExecStop=单元文件中没有指定命令,所以SIGTERM向进程发送a 。

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

  3. 因为SendSIGKILL设置为noSIGKILL( FinalKillSignal)不会发送到进程,进程继续运行。

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

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

KillMode=none您已经使用的选项完全避免了进程终止逻辑。但是,结果与这种方法相似。单元状态变为非活动状态,而进程继续运行。

作为附加说明,90 秒超时可以配置为TimeoutStopSec.