管道故障的奇怪案例

Curious case of failed pipe

谁能告诉我以下问题的可能原因。大多数时候我可以 运行 ( set -o pipefail; ldd --version | head -n 1; echo $? ) 并得到以下内容。

$ ( set -o pipefail; ldd --version | head -n 1; echo $? ) 
ldd (Ubuntu GLIBC 2.23-0ubuntu9) 2.23
0

但随后它会随机开始失败

$ ( set -o pipefail; ldd --version | head -n 1; echo $? ) 
ldd (Ubuntu GLIBC 2.23-0ubuntu9) 2.23
141

我在 Ubuntu 16.04 x86_64 和 RHEL 7.3 ppc64le 机器上看到它的价值

141EINIT。即进程中断。

发生的事情是 head -1 在读取第一行后关闭其输入流。当 ldd 尝试写入已关闭的管道时,失败并显示 EINIT.

通常您看不到这一点 - 在 head 执行了它想要的操作后,程序会出错并退出,但您看不到错误结果。但是因为你有 set -o pipefail,你会看到错误。

这是间歇性的,因为管道中有缓冲,调度是不可预测的。有时 lddhead 关闭管道之前完成写入。

如果你做 ldd | echo 你可以一直看到失败(因为 echo 立即关闭标准输入),你可以一直看到它成功 ldd | cat (因为 cat 总是消耗直到EOF).