web-dev-qa-db-ja.com

バギーなsystemdサービスがSIGKILL経由で終了するように設定する

バックグラウンド

新しいサービス_foo_daemon_のsystemdスクリプトを作成するように依頼されました。このスクリプトは時々「不良状態」になり、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_

質問

_foo_daemon_のsystemdスクリプトを設定して、ユーザーがサービスを停止/再起動しようとするたびにsystemdが次のようになるようにするにはどうすればよいですか。

  • SIGTERMを介して_foo_daemon_の正常なシャットダウンを試みます。
  • _foo_daemon_のシャットダウン/終了が完了するまでに最大2秒かかります。
  • プロセスがまだ生きている場合は、SIGKILLを介して_foo_daemon_の強制シャットダウンを試みます(したがって、PIDがリサイクルされ、systemdが誤ったPIDに対してSIGKILLを発行するリスクはありません)。私たちがテストしているデバイスは、多数のプロセスを迅速に生成/フォークします したがって、問題を引き起こすPIDリサイクルについては、まれですが非常に現実的な懸念があります。
  • 実際には、PIDのリサイクルに偏執しているだけの場合は、スクリプトがプロセスのPIDに対してSIGKILLを発行するだけで問題ありません。

20
Cloud

systemdはすでにこれをそのままサポートしており、 デフォルトで有効 です。

カスタマイズする必要があるのは、TimeoutStopSec=で実行できるタイムアウトだけです。例えば:

[Service]
TimeoutStopSec=2

これで、systemdはSIGTERMを送信し、サービスが終了するまで2秒待機します。終了しない場合は、SIGKILLを送信します。

サービスがsystemdに対応していない場合は、PIDFile=を使用してPIDファイルへのパスを提供する必要がある場合があります。

最後に、デーモンが多くのプロセスを生成すると述べました。この場合、KillMode=control-groupを設定すると、systemdがcgroup内のすべてのプロセスにシグナルを送信します。

27
Michael Hampton

Type=oneshot、タイムアウトエラーのために終了する完全な例を次に示します。

[Unit]
Description=timeout test

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