web-dev-qa-db-ja.com

システムが強制終了されるべきではない状態にある場合は、システムを強制終了しないでください。

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システムでこれをどのように達成できますか?

4
Jan Jaap

この回答は主に systemd.kill のドキュメントに基づいていますが、いくつかのテストを行った後で更新されています。確かに、この問題に対する完全な解決策ではありません。

ユニットファイルで SendSIGKILL=no を設定すると、プロセスが強制終了されるのを防ぐことができます。最初のSIGTERMを送信できるようにするには、KillModeオプションをデフォルト値のcontrol-groupに戻す必要があります。

これらの設定を使用すると、systemctl stop machine.serviceを実行すると次のように機能します。

  1. ユニットファイルにはExecStop=コマンドが指定されていないため、SIGTERMがプロセスに送信されます。

  2. 90秒後に(DefaultTimeoutStopSec)、systemdは強制的にプロセスを終了することを検討します。

  3. SendSIGKILLnoに設定されているため、SIGKILLFinalKillSignal)はではありませんプロセスに送信され、プロセスは実行を継続します。

実際、systemctl stopのプロセスに送信されるシグナルはSIGTERMのみです。 SIGTERMの処理はアプリケーション自体で処理されるため、systemctl stopは意図したとおりに機能するはずです。リモートマシンがダウンするとアプリケーションを停止し、リモートマシンが稼働するとタイムアウトします。

このアプローチの問題は、Micha Mi Politowskiのコメントで指摘されています。つまり、systemdは、停止タイムアウトの期限が切れると、ユニットが故障したと見なします。これはプロセス自体には影響しませんが、systemdのプロセスの視点を変更します。ユニットがこの状態のときに別の「systemctl start」コマンドを発行すると、2つのプロセスが発生します。

すでに使用したKillMode=noneオプションは、プロセスを強制終了するロジックを完全に回避します。ただし、結果はこのアプローチに似ています。ユニットの状態は非アクティブに変わりますが、プロセスは実行し続けます。

追加の注記として、90秒のタイムアウトは TimeoutStopSec で構成できます。

4
Haxiel