如何将tail -f输出重定向到curl(HTTP流)?

6
我希望能从嵌入式设备中收集实时日志。由于设备命令有限,如果我能使用shell脚本来完成这个任务就太好了。
那么,我可以像这样做吗:tail -f /var/logs/some-log.log | curl -X POST --data-urlencode @- http://<log-collaction.website>
我已经尝试过很多方法,但都失败了。例如:
ping www.google.com | while read -r LINE; do curl -X POST --silent --data-binary $LINE "http://localhost:8080/"; done

以上命令可以生效,但它会逐行发布消息。然而,如果我有大量内容要发送,我认为性能不佳。

我知道HTTP/1.1支持分块编码。如何将程序的标准输出重定向到curl或HTTP流(可能是长连接)?

谢谢


尝试使用命名管道? - Thirupathi Thangavel
3
问题在于你需要告诉curl何时考虑一个负载包完成并发送它。根据你当前的尝试,它将会一直等待,因为tail命令永远不会终止,就像使用tail -f时你的终端会一直"挂起"直到你终止该进程。 - arkascha
我能想到两个选项:将数据分块成更大的片段以进行多个curl调用,或者使用不同的协议,比如https://en.wikipedia.org/wiki/WebSocket。 - Nick Russo
2个回答

4
您可以使用像buffer这样的工具(或者更好的mbuffer)来结合这两种策略。
tail -f  /var/logs/some-log.log | buffer | while read -r LINE; do curl -X POST --silent --data-binary $LINE "http://localhost:8080/"; done

这样做可以减少curl向你的webservice发出的HTTP请求次数(但可能会导致连接中断时丢失一些日志记录)。
然而,我同意Nick Russo的看法,实现Websockets可能是一个更好的想法。
希望这有所帮助!

我认为“while read”结构将继续将流分成行,因此curl将运行相同的次数,对吗?如果行不重要,也许可以使用LINE = $(dd count = 100)代替read? - Nick Russo
啊,是的,你说得对。另一个答案巧妙地使用了 dd 来避免这个问题。 - Bart Van Loon

0

这是一个不在乎换行符的分块策略的开始:

while sleep .1; do uptime; done | while LINE=$(dd iflag=fullblock count=2); do echo "$LINE"; done

第一个while循环只是一个虚拟数据生成器,使得这个例子变得简单易用。结尾处的echo代表了curl命令。

以下是一种关注换行符的策略:

#!/bin/bash

count=0
while sleep .1; do uptime; done | while read -r LINE
do
  count=$[count+1]
  if test "$count" -ge 10
  then
    echo "$ACCUMULATOR"
    ACCUMULATOR="$LINE"
    count=0
  else
    ACCUMULATOR+="
$LINE"
  fi
done

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接