管道输出到三通时管道故障 (141) -- 为什么?

Jon*_*nah 8 bash tee

一个例子应该澄清我的问题。这种行为对我来说很有意义:

$ echo hi | cat
hi
$ echo hi | tee >(cat)
hi
hi
Run Code Online (Sandbox Code Playgroud)

第一种情况是显而易见的。在第二种情况下,我们使用命令替换将“hi”通过管道传输到 tee,一个“hi”由tee'dcat打印,而另一个由tee's pass through pipe打印。到现在为止还挺好...

但是在这种情况下,第一个“hi”会发生什么:

$ echo hi | tee >(echo yo)
yo
Run Code Online (Sandbox Code Playgroud)

返回码是 141,管道失败。什么可能导致这种情况?

我正在运行 Mac OSX El Capitain,在默认终端应用程序中运行 bash

G-M*_*ca' 11

我想我已经想出了如何调整您的体验以将其变成其他人能够重现的东西:

$ (echo hello; sleep 1; echo world) | T恤 >(猫)
你好
你好                                                       ……而且,经过短暂的延迟,
世界
世界

$回声“$?”
0

$ (echo hello; sleep 1; echo world) | 三通>(回声哟)
哟
你好

$回声“$?”
141

正如您希望理解的那样, 创建一个管道到正在运行的进程。的标准输入连接到命令行上的其他命令(在本例中为)可以打开和写入的路径名。当is 时,进程坐在那里并从 stdin 读取,直到它得到一个 EOF。在这种情况下,将它从标准输入读取的所有数据写入管道没有问题。>(command)commandcommandteecommandcattee

但是,当commandis 时echo?yo,进程写入yo标准输出并立即退出。这会导致问题tee; 当它写入另一端没有进程的管道时,它会收到一个 SIGPIPE 信号。

显然,OS X 的版本tee 首先在命令行上写入文件,然后是其标准输出。因此,在您的示例 ( echo hi | tee >(echo yo)) 中, tee在第一次写入时就出现管道故障。而teeLinux 和 Cygwin 上的版本首先写入 stdout ,因此它设法hi在它死之前写入屏幕。在我的增强示例中,tee它在写入hello管道时死亡,因此它没有机会读取和写入world.