优雅地停止带有子进程的 python 守护进程
Gracefully stopping python daemon with child proceses
我正在尝试以传统的 start/stop/restart 方式实现一个 python 守护进程来控制消费者到消息队列。我已经成功地使用 python-daemons to create a single consumer, but I need more than one listener 作为消息量。这导致我在我的 运行 函数中实现多处理库,并调用 os.kill
停止函数:
def run(self):
for num in range(self.num_instances):
p = multiprocessing.Process(target=self.start_listening)
p.start()
def start_listening(self):
with open('/tmp/pids/listener_{}.pid'.format(os.getpid()), 'w') as f:
f.write("{}".format(os.getpid()))
while True:
// implement message queue listener
def stop(self):
for pid in os.listdir('/tmp/pids/'):
os.kill(int(os.path.basename(pid)), signal.SIGTERM)
shutil.rmtree('/tmp/pids/')
super().stop()
这几乎没问题,但我真的很想正常关闭子进程并进行一些清理工作,其中包括日志记录。我阅读了有关信号处理程序的信息,因此我将 signal.SIGTERM
切换为 signal.SIGINT
并向守护进程添加了一个处理程序 class.
def __init__(self):
....
signal.signal(signal.SIGINT, self.graceful_stop)
def stop(self):
for pid in os.listdir('/tmp/pids/'):
os.kill(int(os.path.basename(pid)), signal.SIGINT)
super().stop()
def graceful_stop(self):
self.log.deug("Gracefully stopping the child {}".format(os.getpid()))
os.rm('/tmp/pids/listener_{}.pid".format(os.getpid()))
...
然而,在测试时,子进程被杀死,但似乎 graceful_stop 函数从未被调用(文件保留,日志记录不被记录,等等)。我是否为子进程实施了错误的处理程序?有没有更好的方法让多个侦听器具有一个控制点?
我明白了。 signal.signal
声明必须显式放入每个子进程的 start_listening
函数中。
def start_listening(self):
signal.signal(signal.SIGINT, self.graceful_stop)
with open('/tmp/pids/listener_{}.pid'.format(os.getpid()), 'w') as f:
f.write("{}".format(os.getpid()))
while True:
// implement message queue listener
我正在尝试以传统的 start/stop/restart 方式实现一个 python 守护进程来控制消费者到消息队列。我已经成功地使用 python-daemons to create a single consumer, but I need more than one listener 作为消息量。这导致我在我的 运行 函数中实现多处理库,并调用 os.kill
停止函数:
def run(self):
for num in range(self.num_instances):
p = multiprocessing.Process(target=self.start_listening)
p.start()
def start_listening(self):
with open('/tmp/pids/listener_{}.pid'.format(os.getpid()), 'w') as f:
f.write("{}".format(os.getpid()))
while True:
// implement message queue listener
def stop(self):
for pid in os.listdir('/tmp/pids/'):
os.kill(int(os.path.basename(pid)), signal.SIGTERM)
shutil.rmtree('/tmp/pids/')
super().stop()
这几乎没问题,但我真的很想正常关闭子进程并进行一些清理工作,其中包括日志记录。我阅读了有关信号处理程序的信息,因此我将 signal.SIGTERM
切换为 signal.SIGINT
并向守护进程添加了一个处理程序 class.
def __init__(self):
....
signal.signal(signal.SIGINT, self.graceful_stop)
def stop(self):
for pid in os.listdir('/tmp/pids/'):
os.kill(int(os.path.basename(pid)), signal.SIGINT)
super().stop()
def graceful_stop(self):
self.log.deug("Gracefully stopping the child {}".format(os.getpid()))
os.rm('/tmp/pids/listener_{}.pid".format(os.getpid()))
...
然而,在测试时,子进程被杀死,但似乎 graceful_stop 函数从未被调用(文件保留,日志记录不被记录,等等)。我是否为子进程实施了错误的处理程序?有没有更好的方法让多个侦听器具有一个控制点?
我明白了。 signal.signal
声明必须显式放入每个子进程的 start_listening
函数中。
def start_listening(self):
signal.signal(signal.SIGINT, self.graceful_stop)
with open('/tmp/pids/listener_{}.pid'.format(os.getpid()), 'w') as f:
f.write("{}".format(os.getpid()))
while True:
// implement message queue listener