如果我在命令行运行命令(如grep)并按^C,则该命令将被正确终止如果我在后台运行grep,然后在其PID上运行kill SIGINT,它同样会被终止。但是如果我在脚本中并在后台从脚本运行grep,则获取其PID,然后使用'kill -s SIGINT $PID',grep没有被杀死。为什么?如果我使用SIGTERM,而不是SIGINT,kill * 确实 * 起作用。
#!/bin/bash
grep -rqa shazam /usr &
PID=$!
kill -s SIGINT $PID
即使我将grep放在一个子进程中,前面有一个SIGINT处理程序(在子进程中),并用SIGINT命中该子进程,也不会调用该处理程序。
#!/bin/bash
( trap 'echo "caught signal"' SIGINT; grep -rqa shazam /usr ) &
PID=$!
kill -s SIGINT $PID
如果我使用SIGTERM而不是SIGINT,陷阱处理程序 * 将 * 被调用,但不会中断grep。如果我将“/bin/kill -s SIGTERM 0”添加到陷阱处理程序,则会显示grep进程终止,但grep在此之前已经完成了它的工作。我意识到Bash可能对不同的信号有不同的默认行为,但是我不明白为什么我的终止SIGINT的调用不同于^C,为什么trap调用对SIGTERM有效,而对SIGINT无效,为什么SIGTERM没有被子进程立即处理。
2条答案
按热度按时间hgb9j2n61#
通过进一步的挖掘,我解决了3个问题中的2个。当我在脚本中后台处理grep时,shell告诉它忽略SIGINT。Bash说在某些情况下,它会等到子命令完成后才处理信号(我现在没有完全理解),但是如果直接用pkill点击grep进程,信号会立即处理。
vof42yt12#
“实际上,bash将在后台进程上禁用SIGINT(和SIGQUIT),并且无法启用它们”Background process and signalsHow SIGINT works
“进一步的后台作业不应该被绑定到启动它们的 shell 程序。如果您退出 shell 程序,它们将继续运行。同样地,它们不应该被SIGINT中断,在默认情况下不应该。当作业控制被启用时,这是自动完成的,因为后台作业在单独的进程组中运行。当作业控制被禁用时,(通常在非交互式shell中),bash使异步命令忽略SIGINT。”Independent Program
Reason why SIGTERM works