如何创建使用带有 systemd 套接字的 python 3 服务?

如何创建使用带有 systemd 套接字的 python 3 服务?

我正在尝试使用 systemd 创建一个服务,其中我使用 python3 创建了一个简单的套接字并将其保留为守护进程,但我已经尝试了几次,但两次都没有成功。今天 systemd 打败了我,但明天是另一天再试一次。

服务器

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)

配置单元文件

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

结果:

● 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.

意图 2 资料来源:systemd 和 python

使用 python 和 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'.

答案1

这里已经为您的情况准备好了简单的 shell 部署命令,您可以更改目录、名称、服务或脚本的描述等等,描述如下:

创建目录并编写脚本

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

设置创建 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

部署 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

应用新服务,启动并检查

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

因此你的 systemd 服务配置将如下所示

[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

在哪里:

Environment="FROM=SYSTEMD"- 如果你想传递给你的 Python 脚本,则需要一些环境变量

Type=simple- 简单的 systemd 服务它将在脚本启动时运行

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

这些参数不允许你的脚本在任何情况下关闭,它将持续启动失败

KillMode=process- 这是你的脚本停止的方式,如果你的 Python 脚本中没有特殊的 SIG 事件,它是通用的

相关内容