定期查看管道并提取自上次查看以来产生的新输出

定期查看管道并提取自上次查看以来产生的新输出

我正在读取管道不断增长的输出(例如 的输出inotifywait)。

我需要定期检查管道输出并提取自上次查看以来产生的所有新输出。

如何在 shell 脚本中执行此操作?我不知道用于谷歌搜索的关键字。

答案1

管道中的数据只能读取一次; “新内容”部分很简单。只需使用 创建一个命名管道mkfifo,将 inotifywait 输出重定向到它>并定期读取管道。

更棘手的部分是读取管道,该管道在某处打开以供写入,而不会阻塞。 dd 可以做到这一点。

这是我用来创建并连续写入管道的设置:

mkfifo foo
( while true ; do date; sleep 1 ; done ) > foo

并读取所有未读数据:

dd iflag=nonblock if=foo bs=1M count=1 of=buffer.txt

您可以更改of=...为您选择的输出文件。

迟早您会从管道中获得部分线路,因此请确保您的脚本可以处理此问题。对于您描述的活动类型,一个好的方法是在追加模式下重复 dd ,直到缓冲区以换行符终止:

buf=buffer.txt
pipe=foo
> $buf # empty the buffer
until [[ $( tail -c1 $buf | od -a ) == *nl* ]] # nl means newline
do
  dd iflag=nonblock oflag=append conv=notrunc if=$pipe bs=1M count=1 of=$buf
  ls -l $buf # see how it grows
  sleep 1 # if the writer dies, this loop will be infinite and we don't want to kill the CPU
done
do_stuff.sh < $buf
# rm $buf

编辑:看来您想在终端处告诉 inotifywait 并转储所有新内容。这样更容易。创建一个类似于whatsnew.sh 的文件:

#!/bin/bash
echo "waiting for first output ... "
while true
do
    n=0
    while read -t0.1 line
    do
        echo "[$line]"
        (( n++ ))
    done
    read -p "$n new lines.  Press any key to try again... " -n1 -s </dev/tty
    echo
done

然后启动它:

inotifywait | whatsnew.sh

相关内容