python - linux - 信号未传递给多命令

标签 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。在这种情况下,信号传递给最终脚本:

$ /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/

相关文章:

c++ - 如何编译独立的 OpenCV 可执行文件?

linux - 将/proc/1/environ 转换为变量脚本

bash - 如何使用 Bash 插入 SQLite 数据库?

linux - 避免 col 的 32KB 长度限制

bash - 如何用多行搜索和替换多行

python - 使用 ffmpeg 将 video.ts 文件转换为 video.mp4

python - 无法将输入转换为时间戳、bday_range(...) - Pandas/Python

python sqlite3多个LEFT JOIN按列分组

python - Tkinter:在主循环中调用事件

linux - 用于访问 linux 终端的 NPM.JS 插件