Systemd:サービスを開始するには、ポートが開くのを待つか、サービスの開始を宣言します。

Systemd:サービスを開始するには、ポートが開くのを待つか、サービスの開始を宣言します。

他のサービス(activemq)が「アクティブ」である必要があり、接続を開始する前に接続をリッスンするために必要なすべてのポートを持ついくつかのサービス(A、B、C)があります。サービスBとCはAに依存します。これは再びactivemqとリッスンポート(特にポート61616)に依存します。

私が経験している問題は、activemqがすべてのポートを開く前にsystemdがactivemqサービスを「アクティブ」としてマークすることです。だから私のサービス(A)が起動して終了します。

私が試したこと:

set:Restart = on-success(または常に)動作しますが、すべてのサービス(ABC)に対してこれを行う必要があります。私はこのルールを適用したくありません。

仕組みは、サービスAに以下を追加することです。

ExecStartPre=/bin/sleep 30 

これにより、サービスAが正しく起動されるため、BとCは追加の構成を必要としません(すべてのサービスA、B、Cに対して対応する「After =」および「Requires =」設定を除く)。しかし、私はこれが正確でクリーンな解決策だとは思わない。

[サービス]で他のオプションも試しましたが、Type = forkなどの何も機能しませんでした。

私が望むもの:

  • すべてのポート(4つあり)または少なくとも最後のポート(問題を引き起こすポート)でリッスンしている場合にのみ、activemqサービスを「アクティブ」としてマークするようにsystemdに指示します。 61616または
  • ポート61616(ある種のRequire = tcp / 61616など)でリッスンした後にのみサービスAを開始してください。

activemq.service ファイルは次のとおりです。

[Unit]
Description=Activemq Servoce
After=local-fs.target                                                                                                                                                                      
After=network.target                                                                                                                                                                       

[Service]                                                                                                                                                                                  
Type=simple                                                                                                                                                                                
SuccessExitStatus=0 143                                                                                                                                                                    
ExecStart=/usr/bin/activemq console                                                                                                                                                        
User=activemq                                                                                                                                                                              
Group=activemq                                                                                                                                                                             
Restart=always
PrivateTmp=true

[Install]
WantedBy=multi-user.target

答え1

ベース:

Systemdは、activemqがすべてのポートを開くまで、activemqサービスを「アクティブ」としてマークします。

そして:

[サービスA]は、受信にactivemqとそのポート(具体的にはポート61616)を使用します。

...systemdのサービス状態の理解を「プロセス実行中」から「プロセス実行中」に変更できます。そしてポートが開いています」ExecStartPostオプションこの使用中のループは、オペレーティングシステムがポートがリスニングされていることを示すまで待機します。

一例:

ExecStartPost=/usr/bin/timeout 30 sh -c 'while ! ss -H -t -l -n sport = :61616 | grep -q "^LISTEN.*:61616"; do sleep 1; done'

これは、ExecStartの後に実行するコマンドをsystemdに提供します。このコマンドは、timeoutデフォルトのアプリケーションが正常に起動せず、30秒以内にポートでリッスンできない場合にエラーを停止するためのものです。このコマンドは、リッスンしているポートをテストするtimeout単純なシェルループをラップします。sh -c ...シェルループ自体は条件が真になるまで実行され、ss ... | grep ...各テスト間に1秒かかります。sleep

これss注文する次のオプションを使用できます。

  • -H- ヘッダーの抑制(このオプションは必須ではありませんが、ノイズを除去したい)
  • -t- TCPソケットのみを表示
  • -l- リスニングソケットのみを表示
  • -n- サービス番号を名前として解釈しないでください -grep後で使用するために番号のままにしてください。
  • sport = :61616- ソースポートが61616のエントリに出力を制限するフィルタ

その後、コマンドはgrep"LISTEN" で始まり、その後に文字列 ":61616" が続く行を探します。これは、デフォルトアプリケーションがそのポートでリッスンを開始したことを示します。この-qフラグはgrepに成功または失敗のみを報告し、出力をエクスポートしないように指示します。なぜなら、我々は行が存在するかどうかに興味があるからです。

デフォルトのアプリケーションの起動中に、systemdはExecStartPostコマンドが終了するまで「start-post」ステータスを表示します。アプリケーションが正常に起動し、30秒以内にポートが開かれると、systemdはステータスを「アクティブ(実行中)」に更新します。エラーが発生した場合、systemdは(例では)プロセス全体を再開しますRestart=alwaysが、そうでない場合は「失敗(結果:終了コード)」を報告し、終了コード「(code = exited、status = 124)」を使用してExecStartPostコマンドを隠すします。 、コマンドがタイムアウトし、基本プロセスが終了することを示します。

関連情報