我试图更好地理解 Linux 上的 SIGPIPE。
我运行了这个实验:{ ls -al /tmp/ ; echo "$?" 1>&2 ; } | head
它回显了141
我所理解的退出代码,该退出代码是给予退出的进程SIGPIPE
之前,我已经做了很多次,但没有理解 的细微差别SIGPIPE
,而且我通常运行set -eEuo pipefail
所以,我试图理解为什么我的由于管道损坏,代码并不是一直失败...所以我运行了另一个实验:( set -o pipefail; { ls -al /tmp/ ; echo "$?" 1>&2 ; } | head; )
那一次我在回显中得到了 0...所以当pipefail
启用时,这是否意味着它SIGPIPE
被抑制了?或者我误解了这里发生的事情?
答案1
ls
即使 的输出比打印的内容长,也可以在head
退出并破坏管道之前设法写入所有输出。这是因为:ls
head
head
阅读的内容可能比最终打印的内容多,- 无论如何,管道都有一个缓冲区。
SIGPIPE 是通过实际写入损坏的管道来触发的。如果在退出ls
之前设法写入所有输出head
,则不会有任何写入行为触发 SIGPIPE。
或者ls
可能无法在head
退出之前写入所有输出。然后它会尝试写入更多内容并收到 SIGPIPE。
由于ls
和head
并行运行,我认为一般来说存在竞争条件。可能会发生某些特定输出ls
随机触发或不触发 SIGPIPE 的情况。
尝试使用yes
而不是ls …
:
{ yes ; echo "$?" 1>&2 ; } | head
或者
( set -o pipefail; { yes ; echo "$?" 1>&2 ; } | head; )
yes
生成的输出不会自行结束,因此head
退出后总会有一个触发 SIGPIPE 的写入行为。上面的每个命令都会给你141
肯定的信息。
这与 无关pipefail
。