我正在尝试通过套接字远程启动元服务。要求:
- 建立连接时套接字应启动元服务
- 元服务应
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
# [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
有效,但这不是一个很好的解决方案。