安全停止进程的正确信号顺序
我有一个运行很久的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 个回答
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把
2
我认为停止一个进程的正确方法是先发送SIGTERM信号,然后在稍微等一下后再发送SIGKILL信号。
如果那个进程以标准的方式处理信号,我觉得SIGINT和SIGABRT信号并不是必要的。SIGINT通常和SIGTERM处理方式相同,而SIGABRT通常是进程自己在调用abort()时使用的(维基百科)。
比起简单的脚本,复杂一点的程序通常会实现自定义的SIGTERM处理,以便优雅地关闭(比如清理所有资源等)。
举个例子,看看Upstart。它是一个初始化守护进程,负责在Ubuntu和其他一些发行版中启动和停止大多数进程。Upstart默认的停止进程的行为是先发送SIGTERM信号,等5秒钟,然后再发送SIGKILL信号(来源 - upstart手册)。
你可能需要进行一些测试,以确定适合你进程的最佳超时时间。