起動時にリスニング ソケットに接続する必要があるサービス X があります。そのターゲット ソケット自体は、systemd によって起動された別のサービス Y によって開かれます。
サービス Y が正常に開始され、リスニング ソケットを開いた後にのみサービス X を開始するようにユニット ファイル (またはその他の方法) で指定する方法はありますか?
初期接続が失敗した場合、サービス X を変更して再試行することはできないことに注意してください。また、サービス Y がリスニング ソケットを開くまでに要する時間はさまざまであるため、固定遅延もうまく機能しません。
答え1
systemd の動作は若干異なります。systemd を設定してソケットを作成し、リッスンするようにします。X などが接続しようとすると、systemd は接続を処理するために Y を起動し、ソケットを渡します。したがって、X は名目上は Y より先に起動できますが、問題にはなりません。その後の接続は Y によって処理されます (接続ごとに Y が再起動されるように設定することもできますが、これは当てはまらないと思います)。
Y への最小限の変更は、作成/バインド自体を実行するのではなく、事前に作成されたソケットを stdin/stdout ファイル記述子として受け入れるようにすることです。
以下は、root としてではなく、試すことができるテスト セットアップです。3 つのユニット ファイルが必要です。systemd に
~/.local/share/systemd/user/mysock.socket
ソケットを作成し、それを渡す方法を指示します。
# create listening socket. on 1st connect run mysock.service
[Socket]
ListenStream=5555
Accept=false
~/.local/share/systemd/user/mysock.service
(同じ名前を持つmysock
) は、誰かがソケットに接続した場合に開始されるサービスです。ここで Y を開始しますが、これは Python に置き換えました。
[Unit]
Description=started from mysock.socket
[Service]
ExecStart=/home/meuh/bin/python/mysock.py
StandardInput=socket
最後に、X サービスにはソケットが必要であることを示すユニットがあります。XI では、ソケットに日付を書き込む socat を使用しています。
~/.local/share/systemd/user/mysockdepend.service
[Unit]
Description=dependent on socket listening
Requires=mysock.socket
[Service]
ExecStart=/usr/bin/socat -U tcp:localhost:5555 exec:/usr/bin/date
Python は標準入力のソケット、つまりファイル記述子 0 を受け取り、それを適切な Python ソケット オブジェクトにラップし、accept()
それに対して読み取り/書き込みを実行します。
~/bin/python/mysock.py
#!/usr/bin/python
# started from /home/meuh/.local/share/systemd/user/mysock.service
# with socket on stdin/stdout
import sys, time, socket, subprocess
def debug(msg):
# time.sleep(3)
subprocess.call(["/usr/bin/logger", msg])
debug("start\n")
s = socket.fromfd(sys.stdin.fileno(), socket.AF_INET, socket.SOCK_STREAM)
while True:
conn, addr = s.accept()
conn.send("hello\n")
while True:
try:
data = conn.recv(100)
debug("got "+data+"\n")
if len(data)<=0: break
except:
break
conn.close()
の後systemctl --user daemon-reload
、Xを次のように実行できるはずです。
systemctl --user start mysockdepend
ログでjournalctl
Y が開始されたこと、および日付を含むデバッグ出力を確認します。
詳しくはこちらソケットのアクティベーションそして2番目それを発明した人から。
答え2
systemdはこのようなケースを次のように処理します。ソケットファイル。
some-socket.socket
ソケットを表すために、という名前の systemd ユニット ファイルが作成されます。
次に、Service X
サービス ファイルにAfter=
ソケットを参照するディレクティブを含めることができます。
ソケット ファイルに関する公式 systemd ドキュメントが役立つはずです。