ソケットを介してリモートでメタサービスを開始しようとしています。必要:
- 接続が確立されると、ソケットはメタサービスを開始する必要があります。
- メタサービスは
Wants=
起動時にすべてのchild()サービスを開始する必要があります。 - 接続が閉じたら、メタサービスを停止する必要があります。
- メタサービスが停止したら、すべての子(
ConsistsOf=
)サービスも停止する必要があります。
複数の接続を期待しないため、複数の接続が確立された場合、要件は定義されません。
試みは次のとおりです。
# simple.socket
[Unit]
Description=Socket
[Socket]
ListenStream=11111
Accept=no
# simple.service
[Unit]
Description=Meta-service
Wants=simple-child.service # Will be a full tree of dependencies
[Service]
ExecStart=-cat - # cat will fail to start because it doesn't accept connections
StandardInput=socket
# simple-child.service
[Unit]
Description=Child1
PartOf=simple.service # Puts a ConsistsOf= relationship in simple.service
[Service]
ExecStart=sleep infinity # Business goes here
ここで問題はいつですかAccept=no
、ExecStart=
着信接続処理を担当します。 cat -
電話しないでくださいaccept()
だからsimple.service
始めません。ExecStart=
接続に使用できますが、accept()
接続が停止したときに閉じることができる別の基本的なツールはありますか?それは最初の接続でも最後の接続でもかまいません。私はそれについて不可知論的です。これは最も簡単な解決策であり、残りの問題も解決します。 systemdが最初の引数をどのaccept()
ように渡すかを理解できるCアプリケーションを使用する例はありますか?それから私は自分のものを書くことができます。走ってみようsockfd
accept(int sockfd, ...)
これただし、バインド()を使用すると常に失敗します。
以下は、以下を使用した別の試みですAccept=yes
。
# simple.socket
[Unit]
Description=Socket
[Socket]
ListenStream=11111
Accept=yes
# [email protected] # Note the template here
[Unit]
Description=Meta-service
Wants=simple-child.service
[Service]
ExecStart=-cat - # now cat will work!
StandardInput=socket
# simple-child.service
[Unit]
Description=Child1
[email protected] # This fails to connect to the instance
[Service]
ExecStart=sleep infinity # Business goes here
この場合、すべてが順調に進み始めました。接続が閉じられると[email protected]
正常に停止しますが、引き続きsimple-child.service
実行されます。[email protected]
正しいインスタンスが参照されないためです。テンプレートの使用を避けたいのですが、simple-child.service
試してみます。
# simple.socket
[Unit]
Description=Socket
[Socket]
ListenStream=11111
Accept=yes
# [email protected]
[Unit]
Description=Meta-service
Wants=simple-child@%i.service % Starts simple-child as a template
[Service]
ExecStart=-cat -
StandardInput=socket
# [email protected] # Newly templated
[Unit]
Description=Child1
PartOf=simple@%i.service # Using %i
[Service]
ExecStart=sleep infinity # Business goes here
この場合、[email protected]
テンプレートは[email protected]:11111-127.0.0.1:49276.service
ですが。作成のみなので、停止すると停止できません。%i
6
[email protected]
[email protected]
[email protected]:11111-127.0.0.1:49276.service
答え1
解決策がありますが、Pythonで書かれているので、依存関係のために理想的ではありません。
# simple.socket
[Unit]
Description=Socket
[Socket]
ListenStream=11111
Accept=no
# simple.service
[Unit]
Description=Meta-service
Wants=simple-child.service
[Service]
ExecStart=/usr/local/bin/listen.py
# simple-child.service
[Unit]
Description=Child1
PartOf=simple.service
[Service]
ExecStart=sleep infinity
Pythonスクリプトは次のとおりです。
#!/usr/bin/env python3
from socketserver import TCPServer, StreamRequestHandler
import socket
class Handler(StreamRequestHandler):
def handle(self):
while True:
c = self.rfile.read(1)
if len(c) == 0:
exit()
class Server(TCPServer):
SYSTEMD_FIRST_SOCKET_FD = 3
def __init__(self, server_address, handler_cls):
TCPServer.__init__(self, server_address, handler_cls, bind_and_activate=False)
self.socket = socket.fromfd(self.SYSTEMD_FIRST_SOCKET_FD, self.address_family, self.socket_type)
if __name__ == "__main__":
HOST, PORT = "12.34.56.78", 12345 # This gets overridden by systemd
server = Server((HOST, PORT), Handler)
server.serve_forever()
接続が確立されると、simple.service
両方がsimple-child.service
開始されます。接続が終了すると、接続は停止しsimple.service
ますが、simple-child.service
関係にもかかわらず何とか停止しませんPartOf=
。追加することは効果がExecStop=systemctl stop simple-child.service
ありますが、simple.service
それほど良い解決策ではありません。