我想将两个并发程序(日志文件中的尾部)的输出捕获到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的单独程序,但我想知道是否有解决方法.
如果有人可以解释为什么它不起作用我会很高兴.
好问题!这个让我感到难过,但我想我知道发生了什么.正在发生的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
.