我在 bash 中观察到以下行为:
{ echo 'foo' ; sleep 10 ; }
-> 标准输出“foo”立即出现,10 秒后命令完成(如预期)
{ echo 'foo' ; sleep 10 ; } > >(grep 'oo')
-> 标准输出“foo”立即出现,10 秒后命令完成(如预期)
{ echo 'foo' ; sleep 10 ; } > >(grep 'oo' | grep 'oo')
-> 标准输出“foo”在 10 秒后出现
{ echo 'foo' ; sleep 10 ; } > >(grep 'oo' >&2)
-> 10 秒后出现标准错误“foo”
为什么命令替换中带有单个 grep 的命令行会立即输出其结果,而带有管道和重定向的变体则要等到睡眠结束?
答案1
你不需要变得那么花哨;你可以观察到同样的效果
{ echo 'foo' ; sleep 10 ; } | grep oo | grep oo
或者
{ echo 'foo' ; sleep 10 ; } | grep oo | cat
或者
- 打开两个终端。转到两者中的同一目录(例如,您的主目录或
/tmp
)。 - 在其中之一,做
{ echo 'foo' ; sleep 10 ; } | grep oo > foo.out
. - 另一方面,
ls -ld foo.out
重复做。
您将看到该foo.out
文件立即出现,但在 10 秒内其大小为 0,之后变为 4 字节长。
简单地说:grep
测试它的(标准)输出是否是终端。如果是,它会按照要写入的输出一样快地写入输出。如果不是,它会缓冲其输出,并写入氮 一次字节,其中氮 通常为 512,但在某些实现中可能有所不同。
答案2
扩展斯科特的答案:
比较
{ echo 'foo' ; sleep 3 ; } | grep oo | cat
和
{ echo 'foo' ; sleep 3 ; } | stdbuf -o 0 grep oo | cat