Bash 如何缓冲和批量处理tail-f输出?
我需要监视一个文件,并将写入该文件的内容发送到web服务。我正试图通过bash脚本实现一个干净、简单的解决方案,例如:Bash 如何缓冲和批量处理tail-f输出?,bash,Bash,我需要监视一个文件,并将写入该文件的内容发送到web服务。我正试图通过bash脚本实现一个干净、简单的解决方案,例如: #!/bin/bash # listen for changes on file specified as first argument tail -F "$1" | while read LINE do curl http://service.com/endpoint --data "${LINE}" done 这非常有效,如。。附加的每一行都将被发送到。 然而,我并
#!/bin/bash
# listen for changes on file specified as first argument
tail -F "$1" | while read LINE
do
curl http://service.com/endpoint --data "${LINE}"
done
这非常有效,如。。附加的每一行都将被发送到。
然而,我并不喜欢这样一个事实,即如果在短时间内追加许多行,我将有同样多的HTTP请求,并且可能会使服务过载
有没有一种聪明的方法来缓冲操作?我能想到这样的事情:
buffer = EMPTY
while LINES are read:
add LINE to buffer
if buffer has more than X LINES
send POST
fi
done
但是在上面的解决方案中,如果每小时发布一行,我只会每X小时更新一次,这是不可接受的。另一个类似的解决方案是在while循环中“time”:如果X秒已经过去,则发送缓冲区,否则等待。。但是流的最后一行可能会无限期保留,因为while循环只有在向文件添加新行时才会触发
目标是使用最少的bash脚本和而不使用第二个进程来实现这一点。所谓第二个进程,我的意思是:进程1从tail-f获取输出并存储它
,进程2定期检查存储的内容,如果超过x秒,则发送POST
我很好奇,这是不是有什么巧妙的办法
谢谢 从字面上说,将伪代码转换为代码:
# add stdbuf -oL if you care
tail -F "$1" | {
# buffer = EMPTY
buffer=
# while LINES are read:
while IFS= read -r line; do
# add LINE to buffer
buffer+="$line"$'\n'
# if buffer has more than X LINES
# TODO: cache the count of lines in a variable to save cpu
if [ $(wc -l <<<"$buffer") -gt "$x_lines" ]; then
# send POST
# TODO: remove additional newline on the end of buffer, if needed
curl http://service.com/endpoint --data "${buffer}"
buffer=
fi
done
}
多亏了他的回答,我以一种相当简单的方式实现了我想要的,结合了最大行数和超时。诀窍是发现管道不一定按线路工作,就像我想的那样……我真傻
仅供将来参考,这是我的解决方案,非常具体,并简化到骨骼:
#!/bin/bash
# sends updates to $1 via curl every 15 seconds or every 100 lines
tail -F "$1" | while true; do
chunk=""
stop=$((`date +%s` + 15))
maxlines=100
while true; do
if (( `date +%s` >= stop )); then break; fi
IFS= read -r -t 15 line && ret=$? || ret=$?
if (( ret == 0 )); then
chunk+=$line$'\n'
maxlines=$((maxlines - 1))
if (( maxlines == 0 )); then break; fi
elif (( ret > 128 )); then break; fi
done
if (( ${#chunk} != 0 )); then
curl http://service.com --data "$chunk";
fi
done
非常感谢,我将看一看您编写的ratelimit.sh脚本,并充分利用它!我认为我的伪代码中提供的解决方案是缺乏的,因为如果只添加x-1行,并且我们有一个x的缓冲区,它们将永远不会被发送!你说得对,需要一条线和一个超时!
#!/bin/bash
# sends updates to $1 via curl every 15 seconds or every 100 lines
tail -F "$1" | while true; do
chunk=""
stop=$((`date +%s` + 15))
maxlines=100
while true; do
if (( `date +%s` >= stop )); then break; fi
IFS= read -r -t 15 line && ret=$? || ret=$?
if (( ret == 0 )); then
chunk+=$line$'\n'
maxlines=$((maxlines - 1))
if (( maxlines == 0 )); then break; fi
elif (( ret > 128 )); then break; fi
done
if (( ${#chunk} != 0 )); then
curl http://service.com --data "$chunk";
fi
done