命令替换内的阻塞/非阻塞管道/重定向

命令替换内的阻塞/非阻塞管道/重定向

我在 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

相关内容