将两个并发程序的输出与bash结合起来

Mar*_*orn 15 unix bash shell

我想将两个并发程序(日志文件中的尾部)的输出捕获到bash中的一个输出流中.

我用这个示例程序进行测试:

function foo { for i in $(seq 1 10); do echo "program $*"; sleep 1; done }
Run Code Online (Sandbox Code Playgroud)

现在以下工作正常

(foo bar & foo baz &) | tee /tmp/output
Run Code Online (Sandbox Code Playgroud)

但是一旦我在混合中添加额外的管道,它就不再起作用了:

(foo bar | grep bar & foo baz &) | tee /tmp/output # does't work
Run Code Online (Sandbox Code Playgroud)

输出变为顺序.我可以制作一个包含grep的单独程序,但我想知道是否有解决方法.

如果有人可以解释为什么它不起作用我会很高兴.

Fat*_*ror 7

好问题!这个让我感到难过,但我想我知道发生了什么.正在发生的grep是缓冲输出.所以,如果你让它运行,你会看到它最终泛滥.如果你碰巧使用GNU grep尝试传递--line-buffered选项:

(foo bar | grep --line-buffered bar & foo baz &) | tee /tmp/output
Run Code Online (Sandbox Code Playgroud)

为了冒险猜测,并且从根本上讲它是什么,我会说这grep是缓冲更多的输出,因为isatty(1)它表明它没有写入TTY(即使你正在观看TTY上的输出tee).通过缓冲更多输出,可以减少write()呼叫次数,并且效率更高.grep在终端中运行和观看输出的熟悉行为是线路缓冲 - 在找到线条时出现.此选项强制grep以该模式运行.

请记住,正如手册页警告的那样,这可能会对性能产生影响grep.