当我发现一个奇怪的问题时,我发现How can I send the stdout of one process to multiple processes using (preferably unnamed) pipes in Unix (or Windows)?的答案正在和grep
一起玩。以下是我所期望的:
$ while [ 1 ]; do sleep 1 ; echo tick; done | tee >(grep -o ti) >(grep -o ic) >(grep tick) >/dev/null
ic
ti
tick
ic
tick
ti
^C
所有三个grep
命令都应用于循环的输出。
但是,如果我将tee
的输出传递给grep(而不是将其重定向到/ dev / null),文件上的grep
就会停止工作:
$ while [ 1 ]; do sleep 1 ; echo tick; done | tee >(grep -o ti) >(grep -o ic) | grep tick
tick
tick
^C
为什么会这样?
答案 0 :(得分:3)
我会猜测......
tee >(grep -o ti) >(grep -o ic) >(grep tick) >/dev/null
tee >(grep -o ti) >(grep -o ic) | grep tick
在第一个命令中,参数从左到右处理,因此grep -o ti
的输出将转换为标准输出,其他两个进程替换也是如此,然后{{1}的标准输出被重定向到tee
(但已经使用原始标准输出启动了进程)。
在第二个命令中,/dev/null
之前已经设置了管道grep tick
,因此>(grep -o ti)
的标准输出沿着管道向下移动。 grep
命令未选择ti
和ic
行。如果您将其更改为grep tick
,您可能也会看到grep i
和ti
行。
我必须将命令调整为:
ic
查看while true; do echo tick; done |
tee >(grep -o ti) >(grep -o ic) | grep i | grep -v tick
和ti
命令。这与使用标准I / O进行缓冲有关; ic
命令的输出将进入管道,因此它被完全缓冲,输出分批显示。除非我放弃了grep
,否则看到替代产出将花费太长时间。
查看输出的更好的命令是:
sleep 1
输出包含如下行:
while true; do echo tick; done |
tee >(grep -o ti) >(grep -o ic) | grep i | uniq
故事的寓意可能是确保每个进程替换的输出都转到已知文件。