2 votes

Comment créer un service Python 3 qui utilise socket avec systemd ?

J'essaie de créer un service avec systemd, où j'utilise python3 pour créer un simple socket et le laisser comme un démon, mais j'ai fait plusieurs tentatives mais dans les deux cas sans aucun succès. Pour aujourd'hui, systemd m'a battu, mais demain est un autre jour pour essayer.

Serveur

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)

Fichier de l'unité de configuration

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

Résultat :

 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.

Intento 2 Sourcer : systemd et Python

socket avec Python et 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'.

3voto

Aleksandr Chendev Points 446

Voici prêt à l'emploi de simples commandes de déploiement Shell pour votre cas, vous pouvez changer les répertoires, le nom, la description du service ou Shell et ainsi de suite, la description est ci-dessous :

Faire le répertoire et le script lui-même

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

Configurer les variables pour créer le service systemd

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

Déployer la configuration du service systemd

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

Appliquer le nouveau service, le démarrer et vérifier

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

En conséquence, la configuration de votre service systemd ressemblera à ceci

[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

Dónde:

Environment="FROM=SYSTEMD" - une variable env si vous voulez passer à votre script Python

Type=simple - simple service systemd il fonctionnera tant que script est en place

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

Ces paramètres ne permettront pas à votre script d'être en panne dans n'importe quelles conditions, il démarrera en panne continuellement.

KillMode=process - C'est ainsi que votre script s'arrêtera, si vous n'avez pas d'événements SIG spéciaux dans votre script Python, c'est universel.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X