我想创建一个作为systemd服务运行的python程序。我希望能够优雅地停止它。我遇到了一个奇怪的行为:当我使用线程时,python程序在systemctl stop example.service
上没有收到SIGTERM信号,但是如果我不使用线程,一切都可以正常工作。示例如下:
无线程。 (服务收到SIGTERM信号并按预期停止):
import signal
import time
import threading
import sys
RUN=True
# catch SIGINT and SIGTERM and stop application
def signal_handler(sig, frame):
global RUN
print("Got signal: "+str(sig))
RUN=False
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
# some working thread inside application
def my_thread():
global RUN
while RUN:
print("sleep")
time.sleep(1.0)
my_thread()
print("Done.")
带有线程。 (程序未收到SIGTERM信号,并且在超时后被SIGKILL强制杀死):
import signal
import time
import threading
import sys
RUN=True
# catch SIGINT and SIGTERM and stop application
def signal_handler(sig, frame):
global RUN
print("Got signal: "+str(sig))
RUN=False
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
# some working thread inside application
def my_thread():
global RUN
while RUN:
print("sleep")
time.sleep(1.0)
# wait for thread to complete and exit
t = threading.Thread(target=my_thread)
t.start()
t.join()
print("Done.")
系统服务文件:
[Unit]
Description=Example service
[Install]
WantedBy=multi-user.target
[Service]
ExecStart=/usr/bin/python /opt/program/main.py
TimeoutSec=60
Restart=on-failure
Type=simple
User=mixo
Group=mixo
请明确说明:我的程序需要多个线程,因此即使我在程序中使用线程,我也希望能够优雅地停止服务。我在做什么错了?
答案 0 :(得分:0)
感谢@Shawn提出了这个旧的post,我现在已经解决了这个问题。
问题在于如何在python中实现信号处理程序。 t.join()
行阻塞了我的主线程,因此无法接收到任何信号。有两种简单的解决方案:
1)使用python 3.x
或2)使用signal.pause()等待这样的信号:
import signal
import time
import threading
import sys
RUN=True
# catch SIGINT and SIGTERM and stop application
def signal_handler(sig, frame):
global RUN
print("Got signal: "+str(sig))
RUN=False
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
# some working thread inside application
def my_thread():
global RUN
while RUN:
print("sleep")
time.sleep(1.0)
# wait for thread to complete and exit
t = threading.Thread(target=my_thread)
t.start()
signal.pause()
t.join()
print("Done.")