子 shell 脚本没有响应发送到前台进程组的终端中断

子 shell 脚本没有响应发送到前台进程组的终端中断

我有一个控制一些附属脚本的主脚本。当我从终端发送中断信号时,父级trap捕获了该信号,但子级没有捕获信号,我不明白为什么。我没有更改默认终端设置(我没有stty在任何地方运行)。

这是我的父脚本和子脚本以及终端输出:

家长:

#!/bin/sh

./child.sh &

for sig in $(kill -l) ; do
    trap "echo parent:$sig" $sig
done

wait

孩子:

#!/bin/sh

cat < /dev/tty &
PID=$!

for sig in $(kill -l) ; do
    trap "echo child:$sig" $sig
done

wait

终端交互:

[prompt]$ ./parent.sh
^Cparent:INT
cat: stdin: Input/output error

[prompt]$

更新

我在 macOS 和 CentOS 上测试了该脚本,出现了上述行为。当我使用默认的 Bourne 兼容 shell 在 FreeBSD 上测试它时,子进程收到的信号是CHLD

答案1

对于由非交互式 shell 异步运行的命令(实际上当未启用作业控制时),SIGINT 和 SIGQUIT 在 POSIX 兼容中被忽略shPOSIX 要求尽管有些 shell 会忽略它。

另一个 POSIX 要求是如果一个信号在 shell 启动时被忽略,你就无法忽略它,所以你就完蛋了。

在这里,您可以使用没有那些烦人的“功能”(至少在当前版本中)的来zsh代替。sh

无论如何,shell 中的信号处理是最不可靠和最便携的方面之一。您会发现 shell 之间以及同一 shell 的不同版本之间的行为差​​异很大。如果你打算尝试做任何不平凡的事情,就要做好被严重拉扯和挠头的准备。

我建议使用不同的语言,这样您可以更好地控制发生的情况。

另外,我不会盲目地处理所有可能的信号,只会处理您期望收到并知道如何处理的信号。例如,捕获 SIGCHLD(shell 本身对此感兴趣,因为它的工作是生成进程并处理其终止)可能不会执行您想要的操作。

相关内容