起動時にリスニングソケットに接続する必要があるサービスXがあります。ターゲットソケット自体は、systemdによって開始された他のサービスYによって開きます。
サービスYが正常に起動し、リスニングソケットを開いた後にのみサービスXを起動するように単位ファイル(または他の手段)に割り当てる方法はありますか?
初期接続が失敗した場合、再試行するようにサービス X を変更することはできません。さらに、固定遅延は、サービスYがリスニングソケットを開く前に他の時間がかかるため、正しく動作しない。
答え1
systemdは少し異なる動作をする傾向があります。ソケットを作成して受信するように systemd を設定し、X などの人が接続しようとすると、systemd は Y を起動して接続を処理し、ソケットを渡します。したがって、名目上、XはYの前に開始できますが、それは問題ではありません。後で接続は Y によって処理されます。 (各接続ごとにYを再起動するように設定することもできますが、あなたの場合ではないようです。)
Yに対する最小限の変更は、独自に作成/バインドするのではなく、事前に生成されたソケットをstdin / stdoutファイル記述子として許可することです。
これは、rootで試すことなく試すことができるテスト設定です。 3つのユニットファイルが必要です。
~/.local/share/systemd/user/mysock.socket
ソケットを作成して渡す方法をsystemdに指示します。
# 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
systemdはこの状況を処理します。ソケットファイル。
some-socket.socket
ソケットを表すためにsystemdという単位ファイルが作成されます。
Service X
これにより、サービスファイルにソケットを参照するディレクティブを含めることができますAfter=
。
ソケットファイルの公式システム文書が役に立ちます。