
Ich habe folgende Einheiten:
test_socket_activation.socket
[Unit]
Description="************** MY TEST SOCKET ***************"
PartOf=test_socket_activation.service
[Socket]
ListenStream=127.0.0.1:9991
[Install]
WantedBy=sockets.target
test_socket_activation.service
[Unit]
Description="********** MY TEST SERVICE *****************"
[Service]
ExecStart=/home/xxx/sysadmin/systemd_units/socket_based_activation/testservice.sh
[Install]
WantedBy=multi-user.target
testservice.sh
#!/bin/bash
echo "Socket Service Triggered" > output.txt
Theoretisch sollte systemd auf 127.0.0.1 Port 9991 lauschen (über test_scocket_activation.socket). Wenn auf den Socket zugegriffen wird, sollte systemd die übergeordnete Einheit (test_scocket_activation.service) aufrufen, die wiederum das in der ExecStart-Direktive (testservice.sh) aufgeführte Skript ausführen sollte, das dann eine Textdatei mit dem Namen output.txt erstellt, um zu melden, dass auf den Socket zugegriffen wurde.
Dies funktioniert wie erwartet (d. h. output.txt wird erstellt, wenn auf den Socket zugegriffen wird), außer dass die Serviceeinheit (test_scocket_activation.service) danach aufgrund von „Startanforderung zu schnell wiederholt, Start verweigert“ fehlschlägt, obwohl auf den Socket nur einmal zugegriffen wird. Der Ausfall des Dienstes löst dann einen Ausfall des zugehörigen Sockets aus, der das Zuhören einstellt.
Ich habe einige Tests durchgeführt, hier sind meine Schritte und Protokollausgaben:
❯ sudo systemctl start test_socket_activation.socket
❯ sudo systemctl status test_socket_activation.socket
● test_socket_activation.socket - "************** MY TEST SOCKET ***************"
Loaded: loaded (/etc/systemd/system/test_socket_activation.socket; disabled)
Active: active (listening) since Thu 2020-03-19 14:08:40 +01; 17s ago
Listen: 127.0.0.1:9991 (Stream)
Mar 19 14:08:40 toshi systemd[1]: Starting "************** MY TEST SOCKET ***************".
Mar 19 14:08:40 toshi systemd[1]: Listening on "************** MY TEST SOCKET ***************".
❯ echo "hallo" | netcat 127.0.0.1 9991
❯ ls
output.txt testservice.sh
❯ sudo systemctl status test_socket_activation.service
● test_socket_activation.service - "********** MY TEST SERVICE *****************"
Loaded: loaded (/etc/systemd/system/test_socket_activation.service; disabled)
Active: failed (Result: start-limit) since Thu 2020-03-19 14:10:42 +01; 9min ago
Process: 2842 ExecStart=/home/mkr/sysadmin/systemd_units/socket_based_activation/testservice.sh (code=exited, status=0/SUCCESS)
Main PID: 2842 (code=exited, status=0/SUCCESS)
Mar 19 14:10:42 toshi systemd[1]: Started "********** MY TEST SERVICE *****************".
Mar 19 14:10:42 toshi systemd[1]: Starting "********** MY TEST SERVICE *****************"...
Mar 19 14:10:42 toshi systemd[1]: test_socket_activation.service start request repeated too quickly, refusing to start.
Mar 19 14:10:42 toshi systemd[1]: Failed to start "********** MY TEST SERVICE *****************".
Mar 19 14:10:42 toshi systemd[1]: Unit test_socket_activation.service entered failed state.
❯ sudo systemctl status test_socket_activation.socket
● test_socket_activation.socket - "************** MY TEST SOCKET ***************"
Loaded: loaded (/etc/systemd/system/test_socket_activation.socket; disabled)
Active: failed (Result: service-failed-permanent) since Thu 2020-03-19 14:10:42 +01; 41s ago
Listen: 127.0.0.1:9991 (Stream)
Mar 19 14:08:40 toshi systemd[1]: Starting "************** MY TEST SOCKET ***************".
Mar 19 14:08:40 toshi systemd[1]: Listening on "************** MY TEST SOCKET ***************".
Mar 19 14:10:42 toshi systemd[1]: Unit test_socket_activation.socket entered failed state.
❯ sudo journalctl -u test_socket_activation.service
-- Logs begin at Thu 2020-03-19 14:05:23 +01, end at Thu 2020-03-19 14:17:29 +01. --
Mar 19 14:10:42 toshi systemd[1]: Starting "********** MY TEST SERVICE *****************"...
Mar 19 14:10:42 toshi systemd[1]: Started "********** MY TEST SERVICE *****************".
Mar 19 14:10:42 toshi systemd[1]: Starting "********** MY TEST SERVICE *****************"...
Mar 19 14:10:42 toshi systemd[1]: Started "********** MY TEST SERVICE *****************".
Mar 19 14:10:42 toshi systemd[1]: Starting "********** MY TEST SERVICE *****************"...
Mar 19 14:10:42 toshi systemd[1]: Started "********** MY TEST SERVICE *****************".
Mar 19 14:10:42 toshi systemd[1]: Starting "********** MY TEST SERVICE *****************"...
Mar 19 14:10:42 toshi systemd[1]: Started "********** MY TEST SERVICE *****************".
Mar 19 14:10:42 toshi systemd[1]: Starting "********** MY TEST SERVICE *****************"...
Mar 19 14:10:42 toshi systemd[1]: Started "********** MY TEST SERVICE *****************".
Mar 19 14:10:42 toshi systemd[1]: Starting "********** MY TEST SERVICE *****************"...
Mar 19 14:10:42 toshi systemd[1]: test_socket_activation.service start request repeated too quickly, refusing to start.
Mar 19 14:10:42 toshi systemd[1]: Failed to start "********** MY TEST SERVICE *****************".
Mar 19 14:10:42 toshi systemd[1]: Unit test_socket_activation.service entered failed state.
Wie Sie oben sehen können, wird auf den Socket nur EINMAL zugegriffen, der Dienst wird ausgelöst und ruft das Skript auf, um die Datei output.txt zu erstellen. Aber kurz darauf schlägt der Dienst fehl, da er mehrere Startversuche unternimmt.
Meine Fragen lauten wie folgt:
Warum wird der Dienst mehr als einmal gestartet, wenn auf den Socket nur einmal zugegriffen wird (über echo "hallo" | netcat 127.0.0.1 9991)?
Wie kann ich vermeiden, dass der Dienst mehrmals gestartet wird, wenn auf den zugehörigen Socket nur einmal zugegriffen wird?
Ich wäre für alle Antworten/Eingaben/Erkenntnisse sehr dankbar, danke.
Antwort1
Sie haben einen Accept=No
Socket erstellt, bei dem dem Dienst der Dateideskriptor des Listening-Sockets übergeben wird und von ihm erwartet wird, dass er Verbindungen akzeptiert.bleib am Laufen. Der Hinweis sollte sein, dass Sie keine Service-Einheit als Vorlage erstellt haben, wie dies für einen Socket erforderlich gewesen wäre, Accept=Yes
bei dem dem Service der verbundene Socket-Dateideskriptor übergeben wird.
Weiterführende Literatur
- Jonathan de Boyne Pollard (2019).
tcp-socket-accept
. nosh-Anleitung. Software. - https://unix.stackexchange.com/a/513663/5132
s6-tcpserver4d
. Laurent Bercot. s6-Netzwerk. skarnet.org.