通过 sed 卷曲管道时出现问题

Trouble piping to curl through sed

我有一个程序 rtl_433,它输出 JSON 行 - 可能一分钟一次或两次,而它是 运行。我需要将该数据作为 HTTP POST 数据传输到 curl。

让事情变得复杂的是这个字符串需要用单引号括起来,而它们不是,所以我需要在将它发送到 curl.

之前添加它

现在,事情是这样的:这很好用:

echo '{"qwer":98}' | curl -vvv -u pi:<password> http://data:1880/rtl433 -H "Content-Type: application/json" -d @-

这会获取 JSON 字符串 '{"qwer":98}' 并将其发送到服务器 (Node-RED),并在那里接收。现在,不幸的是,我必须自己添加那些单引号,所以我找到了一个 sed 命令,我 运行 使用 ping:

进行了测试
$ ping 8.8.8.8 | sed -e "s/.*/'&'/"
'PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.'
'64 bytes from 8.8.8.8: icmp_seq=1 ttl=59 time=18.8 ms'
'64 bytes from 8.8.8.8: icmp_seq=2 ttl=59 time=19.1 ms'
'64 bytes from 8.8.8.8: icmp_seq=3 ttl=59 time=20.4 ms'
'64 bytes from 8.8.8.8: icmp_seq=4 ttl=59 time=18.9 ms'
^C

完美!这正是我所需要的——现在我需要对 rtl_433:

的输出使用 sed
$ rtl_433 -M level -F json | sed -e "s/.*/'&'/"
rtl_433 version unknown inputs file rtl_tcp RTL-SDR SoapySDR
Use -h for usage help and see https://triq.org/ for documentation.
Trying conf file at "rtl_433.conf"...
Trying conf file at "/home/pi/.config/rtl_433/rtl_433.conf"...
Trying conf file at "/usr/local/etc/rtl_433/rtl_433.conf"...
Trying conf file at "/etc/rtl_433/rtl_433.conf"...
Registered 145 out of 175 device decoding protocols [ 1-4 8 11-12 15-17 19-21 23 25-26 29-36 38-60 63 67-71 73-100 102-105 108-116 119 121 124-128 130-149 151-161 163-168 170-175 ]
Detached kernel driver
Found Rafael Micro R820T tuner
Exact sample rate is: 250000.000414 Hz
[R82XX] PLL not locked!
Sample rate set to 250000 S/s.
Tuner gain set to Auto.
Tuned to 433.920MHz.
Allocating 15 zero-copy buffers

'{"time" : "2022-02-16 09:15:40", "model" : "AlectoV1-Rain", "id" : 130, "channel" : 0, "battery_ok" : 1, "rain_mm" : 273.500, "mic" : "CHECKSUM", "mod" : "ASK", "freq" : 433.911, "rssi" : -1.516, "snr" : 40.628, "noise" : -42.144}'

完美!现在我需要做的就是将 that 传送到 curl:

$ rtl_433 -M level -F json | sed -e "s/.*/'&'/" | curl -vvv -u pi:<password> http://data:1880/rtl433 -H "Content-Type: application/json" -d @-

而且 - 什么都没有!什么都没有。 rtl_433 打印所有初始内容 - 然后几分钟内什么也没有。而且 Node-RED 也完全没有收到任何东西。

这里真的是一头雾水。一切都自己运作,但当我将它们组合在一起时,我什么也得不到。甚至没有错误消息。我错过了什么?

编辑:我看到了将 --unbuffered 添加到 sed 命令的建议,但这并没有改变任何东西。

这里的问题是 rtl_433 永远不会退出,它只会为收到的每条消息打印行。

这是一个问题,因为 curl 将等到它收到一个 EOF(文件结尾)标记时才知道它何时收到了它需要在 HTTP 请求中发送到的所有有效负载,但是当然它永远不会得到这个。 rtl_433 退出时会自动添加 EOF。

您最好的选择可能是从单行脚本转移到适当的 bash 命令,一次从 rtl_433 读取一行,然后在该行之前运行 sed将其传递给卷曲。

例如

#!/bin/bash

rtl_433 -M level -F json | {
  while IFS= read -r line
  do
    echo $line | sed -e "s/.*/'&'/" | curl -vvv -u pi:<password> http://data:1880/rtl433 -H "Content-Type: application/json" -d @-
  done
}