首页 > 解决方案 > 使用管道在 shell 脚本中使用 mosquitto

问题描述

我在 openWRT 设备上使用 mosquitto 从服务器接收一些数据,然后将相同的数据发送到本地打印机以打印这些数据。

我正在使用这个脚本来接收数据

mosquitto_sub -h "${HOST}" -k 30 -c -p 8883 -t "${TOPIC}" -u "${USERNAME}" -P "${PASSWORD}" --id "${ID}" | /bin/sh /bin/printer_execute "${TOPIC}" "${PRINTER}" "${USERNAME}" "${PASSWORD}"

和printer_execute代码:

    #!/bin/sh

TOPIC="${1}"
PRINTER="${2}"
USERNAME="${3}"
PASSWORD="${4}"

while read MSG
  do
    echo "input: ${MSG}"
      echo "INPUT MSG: " "${MSG}" >> /root/log
      RES=`curl -m 2 --header "Content-Type: text/xml;charset=UTF-8" --header "SOAPAction: ''" --header "If-Modified-Since: Thu, 01 Jan 1970 00:00:00 GMT" --data "${MSG}" "http://${PRINTER}/cgi-bin/epos/service.cgi?devid=local_printer&timeout=5000"`
      mosquitto_pub -h ${HOST_PLACEHOLDER} -p 8883 -t "${TOPIC}-response" -m "${RES}" -u "${USERNAME}" -P "${PASSWORD}"
    echo "RESULT CURL: " "${RES}" >> /root/log
done

此解决方案每秒消息数相对较低,但当音量过高时,printer_execute 代码将停止工作。我对 shell 脚本很陌生,我猜这个问题可能是由管道和 while 读取模式或 while 退出条件引起的,但我不太确定。

任何人都有一些想法或发现类似的问题并知道如何解决这个问题?

编辑:根据我试图这样做的答案:

EDIT2:对不起,在第一次编辑中,我刚刚添加了我修改的内容,但整个脚本都是这样的,变量的范围应该是正确的。

#!/bin/sh
TOPIC="${1}"
PRINTER="${2}"
USERNAME="${3}"
PASSWORD="${4}"
PrintOne(){
    MSG="${1}"
    RES=$(curl [params])
    mosquitto_pub -h [host] -p 8883 -d -t "${TOPIC}-response" -m "${RES}" -u "${USERNAME}" -P "${PASSWORD}"
    echo "RESULT CURL: " "${RES}" >> /root/log
}

while read msg ; do
        PrintOne "$msg" &
done

使用 printone 和 appersand 这会收到一条消息并停止工作,没有 & 就像以前一样。

标签: shellmosquittoopenwrt

解决方案


您可以尝试创建一个函数来处理一条消息并在后台调用它(通过附加一个&符号),以便您可以快速并行响应 - 这将使您花费更长的时间来处理每条消息......一段时间. 如果您的消息不断地以比您处理它们的速度更快的速度到达,那么将不可避免地出现积压。

像这样的东西:

#!/bin/bash

PrintOne(){
   echo "Received $1"
   curl ...
   mosquitto_pub ...
   echo $RESULT
}

while read msg ; do
    PrintOne "$msg" &
done

如果你想要一个小例子。将代码更改为此并将其另存为go,并使其可执行chmod +x go

#!/bin/bash

PrintOne(){
   echo "Received $1"
   sleep 2
   echo "Finished $1"
}

while read msg ; do
    PrintOne "$msg" &
done

现在发送 10 行:

seq 10 | ./go

然后删除&符号,并再次执行完全相同的操作,您将看到不同之处。


我的答案的更完整版本如下:

#!/bin/bash

PrintOne(){
   TOPIC="${1}"
   PRINTER="${2}"
   USERNAME="${3}"
   PASSWORD="${4}"
   curl ...
   mosquitto_pub ...
   echo $RESULT
}

while read msg ; do
    PrintOne "${1}" "${2}" "${3}" "${4}" &
done

推荐阅读