用子进程优雅地停止python守护进程

时间:2018-06-20 12:58:58

标签: python python-3.x asynchronous multiprocessing daemon

我正在尝试以传统的start / stop / restart样式实现python守护程序,以控制使用者进入消息传递队列。我已经成功地使用python-daemons创建了一个使用者,但是我需要多个listener来处理大量消息。这导致我在run函数中实现了多处理库,同时对stop函数进行了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并将处理程序添加到守护程序类。

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函数(保留文件,不记录日志,等等)。我是否为子进程实现了错误的处理程序?是否有更好的方法来使多个侦听器具有单个控制点?

1 个答案:

答案 0 :(得分:0)

我知道了。 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