我试图理解为什么在此设置下信号无法正确传递。 简单测试,我有一个 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。在这种情况下,信号不传递给最终脚本:
$ /bin/sh -c "echo foo; python ~/tmpcode/signal_test.py" &
[8] 8015
$ kill 8015
如果我尝试使用 && 而不是 ;,同样的事情也会发生 我试图了解这里发生了什么,以及是否有办法让信号链通过。 旁点:脚本运行多链命令的主要原因是因为第一个命令设置了一些环境供第二个使用。
信号测试.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)
最佳答案
让我解释一下细节。
bash返回的数字不是pid,是pgid(进程组id)
当您在 shell 中运行命令时,shell 将创建一个新的进程组。该组将包含命令中的所有进程。 pgid与leader进程的pid相同。
进程组在多任务这个词中的意思是任务,shell 可以使用 bg(^Z)/fg 在组之间切换。 shell(实际上是 pty,另一个故事)生成的所有信号(如 ^C)将发送到整个组而不是领导进程。
shell创建多进程还是单进程时?
答案很明显,当单个进程无法处理命令时,shell 将创建多个进程。
在第一个例子中
$/bin/sh -c "python ~/tmpcode/signal_test.py" &
[8] 6207
发出单个命令,因此子 shell 本身 (/bin/sh
) 变为 python
。注意,即使只有一个进程,仍然有一个包含唯一进程的新进程组。
在第二个例子中
$ /bin/sh -c "echo foo; python ~/tmpcode/signal_test.py" &
[8] 8015
下发了两条命令,单进程无法完成任务,需要多进程:
/bin/sh
echo
python
创建一个包含这三个进程的进程组。
如何向进程组发送信号?
使用
kill <SIGNAL> -<pgid>
pgid 前面的减号是必不可少的。
关于python - linux - 信号未传递给多命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53227532/