You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UPS数据采集时mosquitto_pub运行一段时间返回4的故障及重试方案咨询

故障原因分析
  • 核心原因是mosquitto_pub的长连接会话失效:你当前在awk中调用mosquitto_pub -l时,awk会在第一次匹配到规则时启动该进程并保持长管道连接,mosquitto_pub仅在启动时向MQTT broker发起一次鉴权,broker默认会对长时间无活动/超过会话有效期的连接自动清理鉴权状态,后续再推送数据时broker就会返回鉴权失败的错误码4。
  • 次要可能原因:TCP长连接意外中断后mosquitto_pub默认不会自动重连,重连时如果出现DNS解析异常、broker临时不可达等情况,也可能抛出类似错误,重启整条命令时会重新建立连接完成鉴权,因此可以恢复。
自动重试方案

以下两种优化方案均可实现故障自动恢复:

方案1:调整调用结构,用shell循环统一管理(推荐)

不要在awk内部调用MQTT推送进程,改为将awk解析后的结果直接输出到标准输出,整条管道的异常都可以被shell捕获并重试:

  1. 先修改parseUPS.awk的核心逻辑,去掉内部调用mosquitto的逻辑,改为直接输出解析后的JSON,同时强制刷新缓冲区避免数据堆积:
/Turn Off/ {
    out=sprintf(....);
    print out;
    fflush();
}
  1. 编写shell循环执行整条链路,异常时自动重启:
#!/bin/bash
while true; do
    # 执行采集解析推送全链路
    ups_status | awk -f parseUPS.awk | mosquitto_pub -h mqtt.local.net -t ups -l
    # 输出错误日志,可根据PIPESTATUS定位具体哪个环节退出
    echo "$(date "+%Y-%m-%d %H:%M:%S") 进程异常退出,各环节退出码:ups_status=${PIPESTATUS[0]} awk=${PIPESTATUS[1]} mosquitto_pub=${PIPESTATUS[2]}" >> /var/log/ups_monitor.log
    # 重试前等待10秒,避免broker被频繁重连触发限流
    sleep 10
done

方案2:awk内捕获管道错误直接退出

如果你不想修改原有调用结构,可以在awk内每次发送后关闭管道、检查错误,异常时直接退出awk进程,触发上层shell循环重启:
修改parseUPS.awk的核心逻辑:

/Turn Off/ {
    out=sprintf(....);
    mqtt_cmd = "mosquitto_pub -h mqtt.local.net -t ups -l"
    print out | mqtt_cmd
    # 关闭当前管道,下次发送会重新启动进程完成鉴权,避免长连接超时
    close(mqtt_cmd)
    # 检查管道执行错误
    if (ERRNO != "") {
        print "MQTT推送失败:" ERRNO > "/dev/stderr"
        # 退出awk进程,触发上层shell循环重启
        exit 1
    }
}

上层shell循环可以用简化版本:

while true; do
    ups_status | awk -f parseUPS.awk
    echo "$(date) 进程异常退出,10秒后重试" >> /var/log/ups_monitor.log
    sleep 10
done

这个方案的优势是每次推送都会重新发起MQTT鉴权,从根源上避免长连接会话超时的问题,2秒一次的推送频率下额外的连接开销完全可以忽略。

内容的提问来源于stack exchange,提问作者Leif Neland

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 06:15:03