怎么会“虽然是真的;”回显 y;完成 | true 会自行消亡,但是 while true;回声 y |猫;完成 |是的`不是吗?

怎么会“虽然是真的;”回显 y;完成 | true 会自行消亡,但是 while true;回声 y |猫;完成 |是的`不是吗?

为了澄清标题问题,我理解前者为什么会死。我不明白为什么后者不这样做,只是为了将 a 添加| cat到循环体中。

也许还有相关的,

while true; do echo y; done

当我这样做时立即死亡^C,但杀戮

while true; do echo y | cat; done

经常需要击打^C不止一次。有时一次有效,有时2或3次有效,然后有时我需要坚持^C一段时间才能死去。

这两种行为都发生在 bash 和 zsh 中,尽管这种^C行为在 bash 中似乎较少见。

对于这两种行为,这并不限于将管道添加到cat. | dd| tee等也会导致它们。甚至echo y | true造成它。循环体中似乎存在任何管道。

为什么循环体中管道的存在会改变循环对信号的响应?

答案1

在 中while true; do echo y; done | true,由于echo是内置的,因此您有一个子 shell 进程,它y\n在循环中写入管道。

返回时true,该管道的读取端被关闭,因此写入写入端会导致 aSIGPIPE被传递到写入进程。在这里,这是运行循环的子 shell 进程。

在 中while true; do echo y | cat; done | true,它cat写入管道。cat通常不是内置的,即使是内置的,在 zsh 和 ksh 之外的 shell 中,所有管道组件始终在子进程中运行。

因此,这里只有正在运行的进程cat会死亡,而运行循环的子 shell 进程会继续运行更多cat进程,这些进程一旦写入y\n标准输出就会死亡。

在 ksh93/ksh2020 中,如果您这样做:

$ builtin cat
$ type cat
cat is a shell builtin
$ set -o pipefail
$ while true; do echo y | cat; done | true; kill -l "$?"
PIPE

这次,cat它是内置的,并且确实在与循环相同的进程中运行(就像cat第一个管道中最右边的命令一样,ksh 不会在子 shell 中运行该命令),因此子 shell 会通过管道true退出并kill -l确认它是被 SIGPIPE 杀死。

相关内容