Bash tail -f 带有 while-read 和管道挂起

Bash tail -f 带有 while-read 和管道挂起

在 Bash 中,管道tail -fread循环会无限期阻塞。

while read LINE0 
do 
    echo "${LINE0}"; 
done < <( tail -n 3 -f /tmp/file0.txt | grep '.*' ) 
# hangs

删除-for | grep '.*',则循环将迭代。

下面的做法是不是悬挂。

tail -n 3 -f /tmp/file0.txt | grep '.*' 

是什么导致了这种行为?

Bash 中是否可以跟踪文件并读取管道表达式?

答案1

在管道中,grep的输出被缓冲。通过 GNU 实现grep,您可以使用--line-buffered(文档在这里);例如:

tail -n 3 -f /tmp/file0.txt | grep --line-buffered '.*' |
  while IFS= read -r LINE0 
  do 
    printf '%s\n' "${LINE0}"
  done  

答案2

Greg's Wiki 有一篇关于缓冲的综合文章:https://mywiki.wooledge.org/BashFAQ/009

对我有用的技术(Popos 20.04、Ubuntu 20.04)用于stdbuf进行行缓冲。他们的例子:

tail -f logfile | stdbuf -oL grep 'foo bar' | awk ...

我的用例:

journalctl --output=json -t poke-stats -f |\
 stdbuf -oL jq -r '.__REALTIME_TIMESTAMP' |\
 stdbuf -oL awk '{print $1-last;last=$1}'

相关内容