대상 소켓이 수신 대기 중인 *후*에만 시스템 서비스를 시작하시겠습니까?

대상 소켓이 수신 대기 중인 *후*에만 시스템 서비스를 시작하시겠습니까?

시작할 때 청취 소켓에 연결해야 하는 서비스 X가 있습니다. 해당 대상 소켓은 systemd에 의해 시작된 다른 서비스 Y에 의해 자체적으로 열립니다.

서비스 Y가 성공적으로 시작되고 청취 소켓을 연 후에만 서비스 X를 시작하도록 단위 파일(또는 다른 방법)에 지정할 수 있는 방법이 있습니까?

초기 연결이 실패하면 재시도하도록 서비스 X를 변경할 수 없습니다. 또한 서비스 Y가 청취 소켓을 열기 전에 다양한 시간이 걸리기 때문에 고정 지연도 제대로 작동하지 않습니다.

답변1

systemd는 약간 다르게 작동하는 경향이 있습니다. 소켓을 생성하고 수신하도록 systemd를 구성하고 X와 같은 사람이 연결을 시도하면 systemd는 Y를 실행하여 연결을 처리하고 소켓에 전달합니다. 따라서 X는 개념적으로 Y보다 먼저 시작할 수 있지만 이는 중요하지 않습니다. 나중에 연결은 Y에 의해 처리됩니다. (각 연결에 대해 Y가 다시 시작되도록 구성할 수도 있지만 귀하의 경우는 아닐 것으로 추정됩니다).

Y에 대한 최소한의 변경 사항은 생성/바인드 자체를 수행하는 대신 미리 생성된 소켓을 stdin/stdout 파일 설명자로 허용하도록 하는 것입니다.

루트가 아닌 사용자가 시도할 수 있는 테스트 설정은 다음과 같습니다. 3개의 유닛 파일이 필요합니다. ~/.local/share/systemd/user/mysock.socketsystemd에게 소켓을 생성하고 전달하는 방법을 알려줍니다.

# 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

파이썬은 stdin의 소켓, 즉 파일 설명자 0을 가져와서 이를 적절한 파이썬 소켓 객체로 래핑하고 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()

a 후에는 다음을 systemctl --user daemon-reload사용하여 X를 실행할 수 있어야 합니다.

systemctl --user start mysockdepend

Y가 시작된 로그 journalctl와 날짜가 포함된 디버그 출력을 확인하세요.

에 대해 읽다소켓 활성화그리고2위그것을 발명한 사람으로부터.

답변2

systemd는 이 사건을 다음과 같이 처리합니다.소켓 파일.

소켓을 나타내기 위해 이름이 지정된 시스템 단위 파일이 some-socket.socket생성됩니다.

그러면 서비스 파일에 소켓을 참조하는 지시문이 Service X포함될 수 있습니다 .After=

소켓 파일에 대한 공식 시스템 문서가 도움이 될 것입니다.

관련 정보