优雅地停止带有子进程的 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