これは必ずしも必要ではありません。
C
サービスがS
ソケット接続を開くことができるようにサービスが準備ができるのを待つ必要がある場合、必ずしもこれを行う必要はありません。むしろ、サービスマネージャーによるソケットの早期開放を利用できます。
Laurent Bercotのs6、私のnoshツールセット、systemd など、いくつかのシステムには、サービスをセットアップする最初の段階で、リスニングソケットを開く方法があります。これらはすべて、リスニングソケットを開くサービスプログラム、および呼び出されたときにリスニングソケットをすでに開いているファイル記述子として受け取るサービスプログラム以外のものを含みます。
具体的には、systemd を使用して、リスニングソケットを定義するソケットユニットを作成します。systemdはソケットユニットを開き、カーネルネットワーキングサブシステムが接続を待機するように設定します。ソケットへの接続を処理するプロセスを起動する場合は、オープンファイル記述子として実際のサービスに渡します。(それはちょうど同じように、二つの方法でこれを行うことができますinetd
ことができますが、内容の議論Accept=true
に対してAccept=false
のサービスがこの答えの範囲を超えています。)
重要な点は、必ずしもそれ以上の順序付けは必要ないということです。カーネルは、サービスプログラムが初期化され、それらを受け入れてクライアントと通信する準備ができるまで、キュー内のクライアント接続をバッチ処理します。
その場合、準備プロトコルが重要です。
systemdには、サービスユニットの設定を使用してサービスごとに指定された、理解可能な一連の準備プロトコルがありますType=
。ここで注目する特定の準備プロトコルは、notify
準備プロトコルです。これにより、systemdはサービスからのメッセージを期待するように指示され、サービスの準備ができると、準備のフラグを立てるメッセージを送信します。systemdは、準備のフラグが立てられるまで、他のサービスのアクティブ化を遅らせます。
これを利用するには、次の2つのことが必要です。
- のコードを変更して、
S
Pierre-Yves Ritschardのnotify_systemd()
関数またはCameron T Normanのnotify_socket()
関数のようなものを呼び出すようにします。
Type=notify
およびでサービスのサービスユニットを設定しNotifyAccess=main
ます。
NotifyAccess=main
systemdにニーズが、システム上の任意のプロセスがにsystemdの通知ソケットにメッセージを送ることができますので、いたずら(あるいは単なる不良の)プログラムからのメッセージを無視するために知っているので(デフォルト)制限があります。
UbuntuBSD、Debian FreeBSD、実際のFreeBSD、TrueOS、OpenBSDなどでこのメカニズムが使用される可能性を排除しないため、Pierre-Yves RitschardまたはCameron T Normanのコードを優先的に使用します。systemdの作者が提供するコードでは除外されています。
回避すべき1つの罠はsystemd-notify
プログラムです。これにはいくつかの大きな問題がありますが、それとともに送信されたメッセージがsystemdによって処理されずに破棄されてしまう可能性があることも重要です。この場合の最も大きな問題は、サービスの「メイン」プロセスとして実行されないことです。そのため、を使用S
して、システムのすべてのプロセスに対してサービスの準備通知を開く必要がありますNotifyAccess=all
。
回避すべきもう1つの罠は、forking
プロトコルがより単純であると考えることです。そうではない。これを正しく行うには、プログラムのすべてのワーカースレッドが実行されるまで(1つには)、親をフォークして終了しないことが含まれます。これは、フォークするデーモンの圧倒的多数が実際にフォークする方法とは一致しません。
参考文献
systemd.service(5)
によれば、はサービスのコントロールグループのNotifyAccess=all
すべてのメンバーからのメッセージを受け入れます。これは、システム上の不正なプロセスを意味するだけではありません。これは、ほとんどのユースケースで十分に安全です。また、他のオペレーティングシステムへの移植性に関する懸念は、OPには関係ありません。これは、ここでSystemdのトピックを扱っているためです。