我有一个长期运行的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而言它们是否具有相同的效果?
答案 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
语句进行捕获。