準備ができているsystemdサービスフラグを使用して、他のサービスが開始する前に準備ができるのを待つことができますか?


8

サービスの初期化が完了し、完全に実行されて他のサービスの準備ができた後にのみ開始する必要がある一連のサービス(たとえばC0C1C9)がありSます。systemdでそれをどのように調整しますか?

にsystemdでのパスの活性化とターゲットとの発注サービスでは、サービスが想定されたSフラグファイルのいくつかの並べ替えを書き出すための機構を有しています。対照的に、ここでは、サービスSが実行するプログラムを完全に制御でき、必要に応じてsystemdメカニズムをプログラムに追加できると仮定します。

回答:


7

これは必ずしも必要ではありません。

CサービスがSソケット接続を開くことができるようにサービスが準備ができるのを待つ必要がある場合、必ずしもこれを行う必要はありません。むしろ、サービスマネージャーによるソケット早期開放を利用できます。

Laurent Bercotのs6私のnoshツールセット、systemd など、いくつかのシステムには、サービスをセットアップする最初の段階で、リスニングソケットを開く方法があります。これらはすべて、リスニングソケットを開くサービスプログラム、および呼び出されたときにリスニングソケットをすでに開いているファイル記述子として受け取るサービスプログラム以外のものを含みます。

具体的には、systemd を使用して、リスニングソケットを定義するソケットユニットを作成します。systemdはソケットユニットを開き、カーネルネットワーキングサブシステムが接続を待機するように設定します。ソケットへの接続を処理するプロセスを起動する場合は、オープンファイル記述子として実際のサービスに渡します。(それはちょうど同じように、二つの方法でこれを行うことができますinetdことができますが、内容の議論Accept=trueに対してAccept=falseのサービスがこの答えの範囲を超えています。)

重要な点は、必ずしもそれ以上の順序付けは必要ないということです。カーネルは、サービスプログラムが初期化され、それらを受け入れてクライアントと通信する準備ができるまで、キュー内のクライアント接続をバッ​​チ処理します。

その場合、準備プロトコルが重要です。

systemdには、サービスユニットの設定を使用してサービスごとに指定された、理解可能な一連の準備プロトコルがありますType=。ここで注目する特定の準備プロトコルは、notify準備プロトコルです。これにより、systemdはサービスからのメッセージを期待するように指示され、サービスの準備ができると、準備のフラグを立てるメッセージを送信します。systemdは、準備のフラグが立てられるまで、他のサービスのアクティブ化を遅らせます。

これを利用するには、次の2つのことが必要です。

  • のコードを変更して、SPierre-Yves Ritschardのnotify_systemd()関数またはCameron T Normanのnotify_socket()関数のようなものを呼び出すようにします。
  • Type=notifyおよびでサービスのサービスユニットを設定しNotifyAccess=mainます。

NotifyAccess=mainsystemdにニーズが、システム上の任意のプロセスがにsystemdの通知ソケットにメッセージを送ることができますので、いたずら(あるいは単なる不良の)プログラムからのメッセージを無視するために知っているので(デフォルト)制限があります。

UbuntuBSD、Debian FreeBSD、実際のFreeBSD、TrueOS、OpenBSDなどでこのメカニズムが使用される可能性を排除しないため、Pierre-Yves RitschardまたはCameron T Normanのコードを優先的に使用します。systemdの作者が提供するコードでは除外されています。

回避すべき1つの罠はsystemd-notifyプログラムです。これにはいくつかの大きな問題がありますが、それとともに送信されたメッセージがsystemdによって処理されずに破棄されてしまう可能性があることも重要です。この場合の最も大きな問題は、サービスの「メイン」プロセスとして実行されないことです。そのため、を使用Sして、システムのすべてのプロセスに対してサービスの準備通知​​を開く必要がありますNotifyAccess=all

回避すべきもう1つの罠は、forkingプロトコルがより単純であると考えることです。そうではない。これを正しく行うには、プログラムのすべてのワーカースレッドが実行されるまで(1つには)、親をフォークして終了しないことが含まれます。これは、フォークするデーモンの圧倒的多数が実際にフォークする方法とは一致しません。

参考文献


1
man systemd.service(5)によれば、はサービスのコントロールグループのNotifyAccess=allすべてのメンバーからのメッセージを受け入れます。これは、システム上の不正なプロセスを意味するだけではありませ。これは、ほとんどのユースケースで十分に安全です。また、他のオペレーティングシステムへの移植性に関する懸念は、OPには関係ありません。これは、ここでSystemdのトピックを扱っているためです。
アミール

1

のマニュアルページsystemd.service(5)、特にType =に関するセクションを参照すると、他のサービスに機能を提供する準備ができているとSystemdが判断する方法は、サービスタイプごとに異なります。

  • の場合Type=simple、デーモンを起動する前に、その通信チャネルをインストールする必要があります(たとえば、ソケットのアクティブ化によってsystemdによって設定されたソケット)。

  • の場合Type=forking、親プロセスは、起動が完了し、すべての通信チャネルがセットアップされたときに終了すると予想されます。

  • の場合Type=dbus、デーモンはD-Busバス上の名前を取得すると予想され、その時点でsystemdはフォローアップユニットの開始を続行します。

  • の場合Type=notify、デーモンsd_notify(3)は起動が完了したときに通知メッセージを送信するか、同等の呼び出しを送信することが期待されます。systemdは、この通知メッセージが送信された後、フォローアップユニットの開始に進みます。

最後のオプション(を介してメッセージを送信するsd_notify)の場合は、systemd-notifyユーティリティを使用できます。NotifyAccess=all

サービスを制御できればS、ユースケースに最適なオプションを選択するか、実装するのが最も簡単なオプションを自由に選択できます。


1

このような:

S.サービス

[Unit]
Description=My main Service

[Service]
Type=notify
ExecStart=/usr/bin/myBinary

C0.service

[Unit]
Description=Dependent service number 0
PartOf=S.service

C1.service

[Unit]
Description=Dependent service number 1
PartOf=S.service

C9.service

[Unit]
Description=Dependent service number 9
PartOf=S.service

/ usr / bin / myBinaryは、初期化が完了したときにsd_notify READY = 1を呼び出します。

あなたは依存関係が動作するようにしたい方法に応じて、あなたが単語の一部を使用することができ、必要、またはBindsToまたは

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