正确的信号顺序,以安全地停止过程

时间:2014-03-06 05:45:24

标签: python signals

我有一个长期运行的Python进程,我希望能够在它挂起并停止报告进度的情况下终止。但是我希望以一种允许它安全清理的方式发出信号,以防它没有完全挂起并且仍然有一些可以优雅地响应信号的运行。在彻底杀死之前发送信号的最佳顺序是什么?

我目前正在做类似的事情:

def safe_kill(pid):
    for sig in [SIGTERM, SIGABRT, SIGINT, SIGKILL]:
         os.kill(pid, sig)
         time.sleep(1)
         if not pid_exists(pid):
             return

有更好的订单吗?我知道SIGKILL完全绕过了这个过程,但SIGTERM / SIGABRT / SIGINT之间是否有任何显着的区别,或者就Python而言它们是否具有相同的效果?

2 个答案:

答案 0 :(得分:2)

我认为停止进程的正确方法是SIGTERM,然后在一个小的超时后跟随SIGKILL。

如果该过程以标准方式处理信号,我认为不需要SIGINT和SIGABRT。 SIGINT通常以与SIGTERM相同的方式处理,并且流程本身通常在abort()(wikipedia)上使用SIGABRT。

比小脚本更复杂的东西通常会实现自定义SIGTERM处理以正常关闭(清理所有资源等)。

例如,看看Upstart。它是一个init守护进程 - 它启动和停止Ubuntu和其他一些发行版中的大多数进程。停止进程的默认Upstart行为是发送SIGTERM,等待5秒并发送SIGKILL(source - upstart cookbook)。

您可能应该进行一些测试以确定流程的最佳超时时间。

答案 1 :(得分:1)

您需要注册信号处理程序,就像在C中一样。

import signal
import sys

def clean_termination(signal):
    # perform your cleanup
    sys.exit(1)

# register the signal handler for the signals specified in the question
signal.signal(signal.SIGTERM, clean_termination)
signal.signal(signal.SIGABRT, clean_termination)

请注意,Python会将SIGINT信号映射到KeyboardInterrupt个异常,您可以使用常规except语句进行捕获。