Weiterführende Literatur

Weiterführende Literatur

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:

  1. 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)?

  2. 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=NoSocket 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=Yesbei dem dem Service der verbundene Socket-Dateideskriptor übergeben wird.

Weiterführende Literatur

verwandte Informationen