【问题标题】:bash standard output can not be redirected into filebash标准输出无法重定向到文件中
【发布时间】:2014-02-21 14:20:05
【问题描述】:

我在看《高级bash脚本》,第31章,有问题。我想不明白。

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

为什么没有任何内容可以输出到日志文件中?
你能给我一个解释吗? 提前谢谢你

【问题讨论】:

  • 因为 /var/log/msg 的尾部没有包含字符串 'error' 的行? tail -f 显示现在正在写入文件的内容,grep 仅过滤掉匹配的行,因此如果没有匹配的行,则不会输出任何内容。
  • @MarkReed,是的,文件'msg'中有几行
  • @ruanhao:最后 10 行必须有 error 文本,否则 tail -f 只是等待新日志出现。
  • 直到 足够 个匹配行被 grep 累积,它使用缓冲,不会将任何内容写入日志文件。
  • 使用tail -f msg | grep --line-buffered 'error' >> logfile是可以的,但我还是想知道为什么'grep'直接输出到stdout时似乎没有缓冲?

标签: linux bash shell pipe io-redirection


【解决方案1】:

作为@chepner cmets,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 中看到升序输出的数字。

在第二个命令中,grepcat 的管道输出是行缓冲的,因此您应该看到每一行的终端输出,即或多或少的连续输出。

【讨论】:

  • 非常感谢您的回答。我想你是对的。是grep 发挥了作用。仅当 stdout 为终端时才使用缓冲区。
猜你喜欢
  • 2013-07-31
  • 1970-01-01
  • 2019-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-21
  • 2015-05-23
相关资源
最近更新 更多