2014-02-21 67 views
2

我正在阅读'高级bash脚本',在第31章中有一个问题。我想不明白。bash标准输出无法重定向到文件

tail -f /var/log/msg | grep 'error' >> logfile

为什么会出现什么可输出到日志文件?
你能给我一个解释吗? 谢谢你

+0

因为/ var/log/msg尾部没有包含字符串'error'的行? 'tail -f'显示了当前正在写入的文件,'grep'只过滤了匹配的行,因此如果没有匹配的行,则不会输出任何内容。 –

+0

@MarkReed,是的,文件'msg'中有行 – ruanhao

+0

@ruanhao:最后10行必须有'error'文本,否则'tail -f'只会等待新日志出现。 – anubhava

回答

3

作为@chepner评论,grep正在使用一个较大的缓冲区(也许4k或更多)来缓冲其标准输出。大多数标准实用程序在管道或重定向到文件时执行此操作。当直接输出到终端时,它们通常只切换到线路缓冲模式。

可以使用stdbuf utility强制grep做其输出的行缓冲:

tail -f /var/log/msg | stdbuf -oL grep 'error' >> logfile 

由于这种效应容易观察到的示范,你可以试试下面这两个命令:

for ((i=0;;i++)); do echo $i; sleep 0.001; done | grep . | cat 

for ((i=0;;i++)); do echo $i; sleep 0.001; done | stdbuf -oL grep . | cat 

在第一个命令中,来自grep .的输出(即,匹配所有线)缓冲进入管道到cat。在我的缓冲区似乎是约4K。随着缓冲区被填充并刷新,您将看到chunks中的升序数字输出。

在第二个命令中,grep的管道输出到cat是行缓冲的,所以你应该看到每行的终端输出,即或多或少的连续输出。

+0

非常感谢你的回答。我想你是对的。它是'grep'扮演的角色。它只在stdout是终端时才使用缓冲区。 – ruanhao