使用while语句时,如何将grep与tee命令结合使用?
管道缓冲引发的输出阻塞问题
命令现象对比
- 以下命令会同时向终端和
/tmp/output.txt输出01:
(echo 01 && sleep 1 && echo 02) | grep -E '[1]$' | tee /tmp/output.txt
- 以下命令会在秒数末尾为1时,向终端输出对应数字(如
01、11):
while true; do date +%S; sleep 1; done | grep -E '[1]$'
- 但以下命令会出现终端挂起,且
/tmp/output.txt无任何内容的情况:
while true; do date +%S; sleep 1; done | grep -E '[1]$' | tee /tmp/output.txt
问题原因
核心是系统的缓冲机制差异:
- 当程序输出目标是终端时,默认用行缓冲——输出一行就立刻刷新缓冲区,内容能马上显示。
- 当输出目标是管道或文件时,默认用块缓冲——只有缓冲区被填满(通常4KB/8KB)才会刷新内容。
第一个命令里,子shell执行完后管道直接关闭,grep匹配到内容就会立即输出,不受块缓冲限制;第二个命令中grep直接输出到终端,行缓冲生效,所以能实时看到结果。
第三个命令中,grep的输出是管道到tee,触发了块缓冲。而date每秒只输出一行短内容,根本填不满缓冲区,导致内容一直被卡在缓冲里,终端看不到输出,文件也没写入,看起来就像命令挂起了。
解决方法
给grep加上--line-buffered参数,强制它使用行缓冲模式:
while true; do date +%S; sleep 1; done | grep -E '[1]$' --line-buffered | tee /tmp/output.txt
这样grep每匹配到一行就立刻输出,tee就能同步把内容写到终端和文件了。
内容的提问来源于stack exchange,提问作者Andreas Tzionis
相关产品推荐
相关产品推荐

