在 Bash 中,当您将多个异步命令通过管道传输给一个消费者时会发生什么?

In Bash, what happens when you pipe several asynchronous commands to one consumer?

考虑这个 Bash 代码:

(cmd1 & cmd2) | consumer

在其标准输入中 consumer 可能会看到什么?

  1. cmd1 输出,然后从 cmd2?
  2. 输出 来自 cmd1
  3. 行任意穿插来自 cmd2?
  4. 的行 来自 cmd1
  5. 字节任意散布于来自 cmd2 的字节?
  6. 还有别的吗?

您可能会看到随机交错的数据,但如果行很短,大多数时候您可能会看到整行交错。

由于进程将它们的 stdout 重定向到管道,这不是交互式设备,输出很可能会被完全缓冲。由于缓冲区将在满时写入,很可能不对应于一行的结尾,因此您可能希望看到交错的缓冲区,每个缓冲区的末尾都有混合行。

Posix System Interfaces, 2.5 Standard IO Streams:

When opened, the standard error stream is not fully buffered; the standard input and standard output streams are fully buffered if and only if the stream can be determined not to refer to an interactive device.

但是,不能保证整个缓冲区会自动写入管道,因此可能存在其他交错效果。

这是一个快速测试:

$ (seq 100000 & seq 100000 &) | sort | uniq -c | awk '!=2' | wc -l
117

awk 程序打印在组合输出中未出现两次的任何行,其中包括所有混合行。所以在那种情况下,大约千分之一的线被混合了。

顺便说一下,在 (cmd1 & cmd2) 中,只有 cmd1 在后台 运行。不过,它们之间仍然是异步的。