Systemdサービスの構成について質問があります。
サービスアプリケーションは、マシンを制御するアプリケーションです。アプリケーション内で、SIGINT、SIGTERM、SIGQUIT、およびSIGHUPがキャプチャされます。マシンが「実行中」の場合、これらの信号は無視され、アプリケーションは終了しません。マシンが「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
今、私は次の質問をします。私が演奏するとき:
Sudo systemctl stop machine.service
SystemctlがSIGTERMを送信するようにしたいので、この方法では、アプリケーションは停止が許可されている場合にのみ停止されます。また、アプリケーションが停止しない場合。 systemctlがプロセスを強制終了しないのはいいことですが、たとえば、ある種の障害やタイムアウトコードを返し、プロセスを停止できない可能性があります。
新しいsystemdシステムでこれをどのように達成できますか?
この回答は主に systemd.kill のドキュメントに基づいていますが、いくつかのテストを行った後で更新されています。確かに、この問題に対する完全な解決策ではありません。
ユニットファイルで SendSIGKILL=no
を設定すると、プロセスが強制終了されるのを防ぐことができます。最初のSIGTERM
を送信できるようにするには、KillMode
オプションをデフォルト値のcontrol-group
に戻す必要があります。
これらの設定を使用すると、systemctl stop machine.service
を実行すると次のように機能します。
ユニットファイルにはExecStop=
コマンドが指定されていないため、SIGTERM
がプロセスに送信されます。
90秒後に(DefaultTimeoutStopSec
)、systemd
は強制的にプロセスを終了することを検討します。
SendSIGKILL
はno
に設定されているため、SIGKILL
(FinalKillSignal
)はではありませんプロセスに送信され、プロセスは実行を継続します。
実際、systemctl stop
のプロセスに送信されるシグナルはSIGTERM
のみです。 SIGTERM
の処理はアプリケーション自体で処理されるため、systemctl stop
は意図したとおりに機能するはずです。リモートマシンがダウンするとアプリケーションを停止し、リモートマシンが稼働するとタイムアウトします。
このアプローチの問題は、Micha Mi Politowskiのコメントで指摘されています。つまり、systemd
は、停止タイムアウトの期限が切れると、ユニットが故障したと見なします。これはプロセス自体には影響しませんが、systemdのプロセスの視点を変更します。ユニットがこの状態のときに別の「systemctl start」コマンドを発行すると、2つのプロセスが発生します。
すでに使用したKillMode=none
オプションは、プロセスを強制終了するロジックを完全に回避します。ただし、結果はこのアプローチに似ています。ユニットの状態は非アクティブに変わりますが、プロセスは実行し続けます。
追加の注記として、90秒のタイムアウトは TimeoutStopSec
で構成できます。