linux-信号未传递给多命令

时间:2018-11-09 14:23:24

标签: python linux bash shell

我试图了解为什么在此设置下信号无法正确通过。 简单测试,我有一个python脚本,注册了一个sigterm处理程序,并在获取时进行打印。如果运行并发送TERM,我已经验证了此工程。

但是,我恰巧是使用useShell = True将其作为python子进程运行。 useShell使用/ bin / sh -c ...启动命令。

如果我这样做,它实际上也可以正常工作:

$/bin/sh -c "python ~/tmpcode/signal_test.py" &
[8] 6207
$ kill 6207
 signum 15

但是,我有执行链接命令的脚本,即/foo/bar.sh;。 some_other_script.py。在这种情况下,信号 not 不会传递给最终脚本:

$ /bin/sh -c "echo foo; python ~/tmpcode/signal_test.py" &
[8] 8015
$ kill 8015

如果我尝试&&而不是; 我试图了解这里发生的事情,以及是否有一种方法可以使信号通过链传递。 观点:脚本运行多链命令的主要原因是因为第一个命令设置了一些环境供第二个命令使用。

signal_test.py:

import time
import signal
import sys

def handler( signum, frame ):
    print( "signum %d\n" % signum ) 
    sys.exit(signum)

signal.signal( signal.SIGTERM, handler )
time.sleep(60)

1 个答案:

答案 0 :(得分:2)

让我解释一下细节。

bash返回的数字不是pid,它是pgid(进程组ID)

在shell中运行命令时,shell将创建一个新的进程组。该组将包含命令中的所有进程。 pgid与Leader进程的pid相同。

进程组表示单词multi-task中的任务,shell可以使用bg(^ Z)/ fg在组之间进行切换。外壳程序(实际上是另一个故事)生成的所有信号(如^ C)都将发送到整个组,而不是领导程序。

当shell创建多个进程或单个进程时?

答案很明显,当命令无法由单个进程处理时,shell将创建多个进程。

在第一个示例中

$/bin/sh -c "python ~/tmpcode/signal_test.py" &
[8] 6207

发出单个命令,因此子外壳程序本身(/bin/sh)成为python。请注意,即使只有一个进程,仍然会有一个包含唯一进程的新进程组。

在第二个示例中

$ /bin/sh -c "echo foo; python ~/tmpcode/signal_test.py" &
[8] 8015

发出两个命令,单个进程无法完成任务,因此需要多个进程:

/bin/sh
    echo
    python

创建了包含这三个过程的过程组。

如何向进程组发送信号?

使用

kill <SIGNAL> -<pgid>

pgid前面的减号是必不可少的。