Wie erstelle ich einen Python 3-Dienst, der Socket mit systemd verwendet?

Wie erstelle ich einen Python 3-Dienst, der Socket mit systemd verwendet?

Ich versuche, mit systemd einen Dienst zu erstellen, bei dem ich mit Python3 einen einfachen Socket erstelle und ihn als Daemon belasse. Ich habe mehrere Versuche unternommen, aber beide Male ohne Erfolg. Für heute hat systemd mich besiegt, aber morgen ist ein neuer Tag, um es zu versuchen.

Server

import socket 
host = '127.0.0.1'
port = 9999
BUFFER_SIZE = 1024 

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as socket_tcp:
    socket_tcp.bind((host, port)) 
    socket_tcp.listen(5) # Esperamos la conexión del cliente 
    conn, addr = socket_tcp.accept() # Establecemos la conexión con el cliente 
    with conn:
        print('[*] Conexión establecida') 
        while True:
            # Recibimos bytes, convertimos en str
            data = conn.recv(BUFFER_SIZE)
            # Verificamos que hemos recibido datos
            if not data:
                break
            else:
                print('[*] Datos recibidos: {}'.format(data.decode('utf-8'))) 
            conn.send(data) # Hacemos echo convirtiendo de nuevo a bytes

Client

import socket
# El cliente debe tener las mismas especificaciones del servidor
host = '127.0.0.1'
port = 9999

BUFFER_SIZE = 1024 MESSAGE = 'Hola, mundo!' # Datos que queremos enviar with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as socket_tcp:
    socket_tcp.connect((host, port))
    # Convertimos str a bytes
    socket_tcp.send(MESSAGE.encode('utf-8'))
    data = socket_tcp.recv(BUFFER_SIZE)

Konfigurationseinheitsdatei

sudo nano /etc/systemd/system/socket_prueba.service
sudo rm -r /etc/systemd/system/socket_prueba.service
[Unit]
Description= Server Relay System: Manager
After=multi-user.target

[Service]
Type=simple
Restart=always
ExecStart=/usr/local/bin/pipenv run python /path/test_server.py

[Install]
WantedBy=multi-user.target

sudo systemctl daemon-reload
sudo systemctl enable socket_prueba.service
sudo systemctl start socket_prueba.service
sudo systemctl status socket_prueba.service

Ergebnis:

● socket_prueba.service - Server Relay System: Manager
     Loaded: loaded (/etc/systemd/system/socket_prueba.service; enabled; vendor preset: enabled)
     Active: failed (Result: exit-code) since Sat 2021-09-25 16:07:17 -05; 58min ago
    Process: 25771 ExecStart=/usr/local/bin/pipenv run python 

/home/path>
   Main PID: 25771 (code=exited, status=2)

sep 25 16:07:17 serversaas systemd[1]: socket_prueba.service: Scheduled restart job, restart counter is >
sep 25 16:07:17 serversaas systemd[1]: Stopped Server Relay System: Manager.
sep 25 16:07:17 serversaas systemd[1]: socket_prueba.service: Start request repeated too quickly.
sep 25 16:07:17 serversaas systemd[1]: socket_prueba.service: Failed with result 'exit-code'.
sep 25 16:07:17 serversaas systemd[1]: Failed to start Server Relay System: Manager.

Absicht 2 Quelle:systemd und python

Socket mit Python und Systemd

● socket_prueba.socket - Socket prueba
     Loaded: loaded (/etc/systemd/system/socket_prueba.socket; disabled; vendor preset: enabled)
     Active: failed (Result: service-start-limit-hit) since Sat 2021-09-25 17:00:47 -05; 4s ago
   Triggers: ● socket_prueba.service
     Listen: 127.0.0.1:9999 (Stream)

sep 25 17:00:47 vidm-OMEN systemd[1]: Listening on Socket prueba.
sep 25 17:00:47 vidm-OMEN systemd[1]: socket_prueba.socket: Failed with result 'service-start-limit-hit'.

Antwort1

Hier sind einfache Shell-Bereitstellungsbefehle für Ihren Fall, die sofort einsatzbereit sind. Sie können Verzeichnisse, Namen, Beschreibungen von Diensten oder Skripts usw. ändern. Die Beschreibung finden Sie weiter unten:

Verzeichnis und Skript selbst erstellen

mkdir /usr/src/python-socket -p

cat > /usr/src/python-socket/python-socket.py << 'EOL'
import socket 
host = '127.0.0.1'
port = 9999
BUFFER_SIZE = 1024 

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as socket_tcp:
    socket_tcp.bind((host, port)) 
    socket_tcp.listen(5) # Esperamos la conexión del cliente 
    conn, addr = socket_tcp.accept() # Establecemos la conexión con el cliente 
    with conn:
        print('[*] Conexión establecida') 
        while True:
            # Recibimos bytes, convertimos en str
            data = conn.recv(BUFFER_SIZE)
            # Verificamos que hemos recibido datos
            if not data:
                break
            else:
                print('[*] Datos recibidos: {}'.format(data.decode('utf-8'))) 
            conn.send(data) # Hacemos echo convirtiendo de nuevo a bytes
EOL

Einrichten von Variablen zum Erstellen des Systemd-Dienstes

SERVICE_NAME=python-socket
SERVICE_DESCRIPTION="Test python service"
SERVICE_COMMAND="/usr/bin/python3 /usr/src/python-socket/python-socket.py"
SERVICE_WORK_DIR=/usr/src/python-socket/
SERVICE_USER=root

Bereitstellen der systemd-Dienstkonfiguration

cat > /etc/systemd/system/${SERVICE_NAME}.service << EOL
[Unit]
Description=${SERVICE_DESCRIPTION}
After=multi-user.target

[Service]
Environment="FROM=SYSTEMD"
WorkingDirectory=${SERVICE_WORK_DIR}
Type=simple
User=${SERVICE_USER}
ExecStart=${SERVICE_COMMAND}
RemainAfterExit=no
Restart=always
RestartSec=2
StartLimitBurst=999999
StartLimitInterval=0
KillMode=process

[Install]
WantedBy=multi-user.target
EOL

Neuen Dienst beantragen, starten und prüfen

systemctl daemon-reload
systemctl enable ${SERVICE_NAME}
systemctl stop ${SERVICE_NAME}
systemctl start ${SERVICE_NAME}
systemctl status ${SERVICE_NAME}

Als Ergebnis sieht Ihre systemd-Dienstkonfiguration wie folgt aus:

[Unit]
Description=Test python service
After=multi-user.target

[Service]
Environment="FROM=SYSTEMD"
WorkingDirectory=/usr/src/python-socket/
Type=simple
User=root
ExecStart=/usr/bin/python3 /usr/src/python-socket/python-socket.py
RemainAfterExit=no
Restart=always
RestartSec=2
StartLimitBurst=999999
StartLimitInterval=0
KillMode=process

[Install]
WantedBy=multi-user.target

Wo:

Environment="FROM=SYSTEMD"- einige Umgebungsvariablen, wenn Sie sie an Ihr Python-Skript übergeben möchten

Type=simple- einfacher systemd-Dienst, der funktioniert, während das Skript aktiv ist

RemainAfterExit=no
Restart=always
RestartSec=2
StartLimitBurst=999999
StartLimitInterval=0

Diese Parameter verhindern, dass Ihr Skript unter irgendwelchen Bedingungen ausfällt, es wird bei einem Fehler kontinuierlich gestartet

KillMode=process- So wird Ihr Skript beendet. Wenn Sie in Ihrem Python-Skript keine speziellen SIG-Ereignisse haben, ist es universell

verwandte Informationen