考虑 Bash shell 中的以下示例
$ echo 'test' | wc -c
5
一切都按预期进行。现在我们将其更改为
$ echo 'test' >&0 | wc -c
test
0
现在,0
输出中的内容非常有意义:echo
已将所有内容发送到stdin
(传统上可写),但没有发送到stdout
,因此没有任何内容通过管道传输到wc
。但是输出是如何出现在控制台中的呢?谁在何时打印了这test
行内容?
最后,第三个测试(适用于支持的平台stdbuf
)
$ stdbuf -i0 -o0 -e0 echo 'test' >&0 | wc -c
0
test
这里发生了什么?为什么顺序改变了?
答案1
of连接到终端,因此当您执行 时,输出就到了stdin
那里。通常,不使用它的标准输入,但它就在那里,就像例如一样。另一方面,如果运行,则会收到“错误文件描述符”错误,因为连接到第二个标准输入的管道对于它来说是只读的。echo
echo 'test' >&0
echo
cat
echo foo | echo test >&0
echo
在您的另一个片段中,我认为发生的情况是,注意到管道已关闭(您将写入侧重定向,因此没有人写入管道)和写入终端之间stdbuf
存在一场竞赛。这与缓冲无关(这实际上并不重要,因为无论如何完成时都必须刷新缓冲区),您可以使用or得到相同的结果。左侧任何使启动速度变慢的东西都会产生影响。另外,请记住,使用 just ,您可能会运行 shell 的内置实现,而使用, or ,则可以运行外部运行。内置速度更快。wc
stdin
echo
echo
strace echo ...
env echo ...
echo
echo | wc
echo
stdbuf
env
strace
echo
一般来说,如果有两个进程同时在某处写入,则无法对写入顺序做出任何假设,除非它们显式同步。