systemd 소켓 연결이 닫히면 하위 서비스 중지

systemd 소켓 연결이 닫히면 하위 서비스 중지

소켓을 통해 원격으로 메타서비스를 시작하려고 합니다. 필요하다:

  1. 연결이 설정되면 소켓은 메타서비스를 시작해야 합니다.
  2. 메타서비스는 Wants=시작 시 모든 child() 서비스를 시작 해야 합니다.
  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=no, ExecStart=들어오는 연결 처리를 담당합니다. cat -전화하지 마세요accept()그래서 simple.service시작되지 않습니다. ExecStart=연결하는 데 사용할 수 있지만 accept()연결이 중지되면 닫을 수 있는 또 다른 기본 도구가 있습니까 ? 그것이 첫 번째 연결일 수도 있고 마지막 연결일 수도 있습니다. 저는 그것에 대해 불가지론적입니다. 이것은 가장 간단한 해결책이며 나머지 문제도 해결합니다. systemd가 첫 번째 인수를 accept()어떻게 전달하는지 알아낼 수 있는 C 응용 프로그램을 사용하는 예가 있습니까 ? 그러면 나는 내 자신의 것을 쓸 수 있습니다. 나는 달리려고 노력한다sockfdaccept(int sockfd, ...)이것, 그러나 바인드()를 사용할 때 항상 실패합니다.

다음은 다음을 사용한 또 다른 시도입니다 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이지만 . 생성만 되므로 중지하면 중지할 수 없습니다 .%i6[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

파이썬 스크립트는 다음과 같습니다:

#!/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그다지 좋은 해결책은 아닙니다.

관련 정보