仅在目标套接字监听*之后*才启动 systemd 服务?

仅在目标套接字监听*之后*才启动 systemd 服务?

我有一个服务 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

并在日志中看到journalctlY 已启动,以及带有日期的调试输出。

阅读套接字激活第二名来自发明它的人。

答案2

systemd 处理这种情况套接字文件

将创建一个名为 systemd 的单元文件some-socket.socket来表示套接字。

然后您的Service X服务文件可以包含After=引用套接字的指令。

有关套接字文件的官方 systemd 文档应该会有所帮助。

相关内容