我正在尝试使用 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
● 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 事件,它是通用的