소켓을 통해 원격으로 메타서비스를 시작하려고 합니다. 필요하다:
- 연결이 설정되면 소켓은 메타서비스를 시작해야 합니다.
- 메타서비스는
Wants=
시작 시 모든 child() 서비스를 시작 해야 합니다. - 연결이 닫히면 메타서비스가 중지되어야 합니다.
- 메타서비스가 중지되면 모든 하위(
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 응용 프로그램을 사용하는 예가 있습니까 ? 그러면 나는 내 자신의 것을 쓸 수 있습니다. 나는 달리려고 노력한다sockfd
accept(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
이지만 . 생성만 되므로 중지하면 중지할 수 없습니다 .%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
파이썬 스크립트는 다음과 같습니다:
#!/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
그다지 좋은 해결책은 아닙니다.