當 systemd 套接字連接關閉時停止子服務
我正在嘗試通過套接字遠端啟動元服務。要求:
- 建立連接時,套接字應該啟動元服務
- 元服務應在啟動
Wants=
時啟動所有子 ( ) 服務- 當連接關閉時,元服務應該停止
- 當元服務停止時,它應該停止所有子 (
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()
連接,但在連接停止時關閉?這可能是第一個或最後一個連接,我對此不可知。那將是最簡單的解決方案,也可以解決其餘問題。是否有使用 C 應用程序的範例,accept()
以便我可以弄清楚 systemd 如何通過sockfd
我們的第一個參數accept(int sockfd, ...)
?然後我可以自己寫一些東西。我嘗試執行它,但在使用 bind() 時一直失敗。這是使用的另一種嘗試
Accept=yes
:# simple.socket [Unit] Description=Socket [Socket] ListenStream=11111 Accept=yes # simple@.service # 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 PartOf=simple@.service # This fails to connect to the instance [Service] ExecStart=sleep infinity # Business goes here
在這種情況下,一切都很好。當連接關閉時,會
simple@XYZ.service
很好地停止,但simple-child.service
會繼續執行。那是因為PartOf=simple@.service
沒有引用正確的實例。我真的更願意避免使用模板simple-child.service
,但讓我們嘗試一下:# simple.socket [Unit] Description=Socket [Socket] ListenStream=11111 Accept=yes # simple@.service [Unit] Description=Meta-service Wants=simple-child@%i.service % Starts simple-child as a template [Service] ExecStart=-cat - StandardInput=socket # simple-child@.service # Newly templated [Unit] Description=Child1 PartOf=simple@%i.service # Using %i [Service] ExecStart=sleep infinity # Business goes here
在這種情況下
simple@.service
,模板化為simple@6-127.0.0.1:11111-127.0.0.1:49276.service
,但%i
僅是6
。它只生成simple-child@6.service
,PartOf=simple@6.service
因此停止時無法simple@6-127.0.0.1:11111-127.0.0.1:49276.service
停止。
我有一個解決方案,但它在 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
確實有效,但這不是一個很好的解決方案。