当 systemd 套接字连接关闭时停止子服务

当 systemd 套接字连接关闭时停止子服务

我正在尝试通过套接字远程启动元服务。要求:

  1. 建立连接时套接字应启动元服务
  2. 元服务应Wants=在启动时启动所有子 ( ) 服务
  3. 当连接关闭时,元服务应该停止
  4. 当元服务停止时,应该停止所有子( 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=noExecStart=负责处理传入连接。 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

# [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有效,但这不是一个很好的解决方案。

相关内容