SIGKILLを介して終了するようにバグのあるsystemdサービスを構成する


20

バックグラウンド

systemd新しいサービスのスクリプトを作成するように依頼されました。これはfoo_daemon、「悪い状態」になることもあり、経由しないこともあります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

質問

どのようにすることができますが、私のセットアップ私のsystemdためのスクリプトをfoo_daemonするように、停止へのユーザーの試みは/サービスを再起動するたびに、systemd以下となります。

  • foo_daemonviaの正常なシャットダウンを試みSIGTERMます。
  • シャットダウン/終了がfoo_daemon完了するまで最大2秒かかります。
  • プロセスがまだ有効な場合は、foo_daemonviaの強制シャットダウンを試行しSIGKILLます(したがって、PIDがリサイクルされたり、間違ったPIDに対してsystemd問題が発生するリスクはありませんSIGKILL)。私たちがテストしているデバイスは、多数のプロセスを迅速に生成/分岐するためPIDリサイクルが問題の原因なることはめったにありませんが、非常に現実的な懸念があります。
  • 実際に、PIDのリサイクルについて単に妄想しているだけであれば、スクリプトはSIGKILL、リサイクルされたPIDを殺すことを心配せずに、プロセスのPIDに対して発行するだけで構いません。


2
2秒で400万以上のPIDを処理するのに十分な速さでプロセスを生成したとしても、systemd 「このpidはまだ生きていますか?このpidはまだ生きていますか?」チェックをループしません必要がないからです。直接の子プロセスがまだ生きているかどうかについてはすでに通知されています(通常のSIGCHLDとwaitpid()によって)。したがって、プロセスがSIGTERMの後に終了したことがわかると、その時点でサービスを単に「非アクティブ」としてマークします。SIGKILLの確認、待機、送信は一切行いません。
-grawity

回答:


26

systemdはこれをすぐにサポートしており、デフォルト有効になっています

カスタマイズしたいのはタイムアウトだけで、これはで実行できますTimeoutStopSec=。例えば:

[Service]
TimeoutStopSec=2

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

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

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


ありがとうございました。最後の質問:サービスがsystemdに対応していないと仮定しましょう。systemdがPIDファイルを作成/管理するために、このサービスのsystemdスクリプトに何を追加できますか??私たちは通常、 `systemctl開始foo_dameon@1.service」を介して、それを起動するので、その影響はスクリプト内のPIDファイルの論理だろうので、また、サービスは、テンプレートユニットを経由してマルチインスタンスすることができ
クラウド

4
@DevNull systemdは、PIDファイルを作成または管理しません。そうする理由はありません。サービスが独自のPIDファイルを作成しない場合、可能であれば(デーモン化の代わりに)フォアグラウンドで実行するように構成Type=simpleし、systemdユニットで設定します。
マイケルハンプトン

1
サービスに依存関係がある場合、Type=forking(サービスが適切に記述されていれば)Type = simpleができない完全に「準備ができた」ときにsystemdに通知するという利点があります。PIDファイルがなくても、デーモン化は問題になりません。systemdはメインプロセスを追跡します。
-grawity

1
@grawity確かに...サービスが実際に提供を開始する前にサービスがデーモン化されるのは私の経験でしたが。systemdを使用するsystemd対応サービスType=notifyはsystemdに最適であり、多くの一般的なサービスはすでにこれを行っています。しかし、おそらくこのレガシーサービスではありません。OPの場合、彼には多くのプロセスを生成するサービスがあります。systemdのドキュメントはこのケースについて警告しています。
マイケルハンプトン

1

誰も必要とType=oneshotは言わなかったので、タイムアウトの失敗のために終了する完全な例を示します。

[Unit]
Description=timeout test

[Service]
Type=oneshot
TimeoutStartSec=2
ExecStart=/bin/sleep 10
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.