stdout 是否可以被两个异步运行的 bourne(或 bash,如果重要的话)子 shell 命令覆盖?
\n\n(tail -f ./file1 & tail -f ./file2) | cat\n
Run Code Online (Sandbox Code Playgroud)\n\n我不关心行顺序,只是每个输出行都由一个输入行组成。I\xe2\x80\x99m 担心某些行可能会被部分覆盖或交错。
\n\n我\xe2\x80\x99 通过运行四个命令进行了测试,每个命令输出一个唯一的行 1500 万次。它似乎有效,但我有点预计它会失败。
\n\n有人可以解释一下这如何不会破坏\xe2\x80\x99t吗?每个子 shell 是否都被缓冲并且一次只有一个子 shell 可以写入标准输出?或者这是如何管理的。
\n\n有一个更好的方法吗?
\n\n(不要介意 I\xe2\x80\x99m在上述子 shell 中用于tail
说明目的。我实际上想运行另外两个命令,一次连续输出一行到标准输出。)
贝壳在那里几乎没有参与。他们所做的就是创建管道并启动这 3 个命令,然后这些命令独立于 shell 并行运行。
这里重要的是两个 tail 命令都将文件描述符写入同一管道的同一写入端。
如果你这样做:
printf foo1 >> file1; sleep 1
printf foo2 >> file2; sleep 1
printf 'bar1\n' >> file1; sleep 1
printf 'bar2\n' >> file2
Run Code Online (Sandbox Code Playgroud)
你会看到的:
foo1foo2bar1
bar2
Run Code Online (Sandbox Code Playgroud)
因为那些都是这么写的。您需要确保您的命令一次输出一整行,并且这些行小于 PIPE_BUF(Linux 上为 4096 字节),以保证 write() 是原子的(它也可以写入多个一次整行,前提是它们都已满并且它们的累积大小小于 PIPE_BUF)。
使用 GNU grep
,您可以通过将命令传递到grep --line-buffered '^'
(tail -f ./file1 | grep --line-buffered '^' &
tail -f ./file2 | grep --line-buffered '^') | cat
Run Code Online (Sandbox Code Playgroud)
这将保证两个write()
命令的输出的每一行都有一个系统调用(在命令不终止其最后一行输出的情况下,grep
将添加缺少的换行符)