我试图通过以两种不同方式启动的脚本来理解我对SIGINT信号的行为。
这是一个简单的python脚本:
import time
while True:
time.sleep(10000)
如果我在后台启动脚本,请检查pid和ppid(注意它与我的终端相同)并用SIGINT杀死它,它可以工作:
user@host [~] > python script.py &
[1] 19077
user@host [~] > ps axo pid,ppid,command | grep script
19077 1055 python script.py
19093 1055 grep script
user@host [~] > kill -INT 19077
Traceback (most recent call last):
File "script.py", line 10, in <module>
time.sleep(10000)
KeyboardInterrupt
[1] + exit 1 python script.py
现在,如果我通过Makefile启动它:
user@host [~] > cat Makefile
all:
python script.py &
user@host [~] > make
python script.py &
user@host [~] > ps axo pid,ppid,command | grep script
19118 1 python script.py
19122 1055 grep script
user@host [~] > kill -INT 19118
user@host [~] > ps axo pid,ppid,command | grep script
19118 1 python script.py
19128 1055 grep script
请注意,现在,它的ppid为1(init,似乎是逻辑)并且它不会被杀死。好像该过程没有收到信号。我改变了我的脚本来自己处理信号:
import time, signal, sys
def signal_handler(signal, frame):
print 'Killed !'
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
while True:
time.sleep(10000)
现在这个过程被我写的处理程序杀死了:
user@host [~] > make
python script.py &
user@host [~] > ps axo pid,ppid,command | grep script
19148 1 python script.py
19152 1055 grep script
user@host [~] > kill -INT 19148
Killed !
user@host [~] > ps axo pid,ppid,command | grep script
19158 1055 grep script
所以我的问题是:为什么当ppid为1或使用Makefile启动时,进程不会被SIGINT杀死?我无法理解这种行为,我知道最好的办法就是用SIGTERM来杀死它,因为它几乎就像一个守护进程,但无论如何我想要理解这一点。
在python中,SIGINT信号被转换为KeyboardInterrupt异常,我试图抓住它而没有任何成功。
我在bash中执行了相同的脚本,行为完全相同。
有什么想法吗?
答案 0 :(得分:1)
信号处理程序继承自父进程,正如您自己演示的那样,可以重新定义。所以make
要么重新定义它。或者,特别是对于SIGINT,可能有一个逻辑在进程失去stdin或其终端时重新定义处理程序,因为SIGINT通常用于Ctrl-C。没有终端,没有Ctrl-C。