为何通过/etc/profile autorun的Python MQTT脚本无法稳定连接Broker?
MQTT脚本手动运行正常,开机自启(/etc/profile)时无限断连重连的解决办法
最近折腾一个控制多LED的Python脚本,用到MQTT和Broker通信,手动在Shell里跑完全没问题,MQTT连接稳得一批;但想着让它开机自动启动,把命令sudo python3 /home/pi/..../main.py &加到/etc/profile里后,脚本倒是能启动,可MQTT连接就疯了——无限循环断开、重连,Broker端反复收到RPiGiulio/Connection/status的0和1状态,根本没法稳定工作。
先贴一下我脚本里MQTT连接相关的代码:
def Connect(client,broker,port,keepalive,run_forever=False): connflag=False delay=5 print('--------------------------------') print("connecting " + client_id) badcount=0 # counter for bad connection attempts while not connflag: logging.info("connecting to broker "+str(broker)) print("connecting to broker "+str(broker)+":"+str(port)) print("Attempts ",badcount) try: res=client.connect(broker,port,keepalive) #connect to broker if res==0: print('--------------------------------') print("Connection established") print('--------------------------------') connflag=True return 0 else: logging.debug("connection failed.") print('--------------------------------') badcount += 1 if badcount>=3 and not run_forever: raise SystemExit #give up elif run_forever and badcount<3: delay=5 else: delay=3 def on_connect(client, userdata, flags, rc): print('--------------------------------') logging.debug("Connected flags"+str(flags)+"result code " + str(rc) + "client RPi Giulio") if rc == 0: print("Connected OK. Returned code = ", rc) print('--------------------------------') client.connected_flag = True client.publish(connected_topic,1,retain=True) else: print("Bad connection. Returned code = ", rc) print('--------------------------------') client.bad_connection_flag = True
Broker那边的状态日志就是反复跳:
RPiGiulio/Connection/status 0 RPiGiulio/Connection/status 1 RPiGiulio/Connection/status 0 RPiGiulio/Connection/status 1 ...(无限循环)
踩坑后的分析
后来查了下,/etc/profile是用户登录时触发的脚本,它的执行环境和手动开Shell跑脚本差不少:
- 环境变量不全:比如
PATH或者脚本依赖的一些配置变量可能没加载全,导致连接Broker时出隐性错误 - 网络没准备好:
/etc/profile执行的时候,系统可能还在初始化网络,这时候脚本去连Broker肯定失败,后续重连也因为环境问题稳不住 - 权限上下文不对:用
sudo在/etc/profile里跑脚本,用户环境和手动执行时不一样,也可能引发连接异常
亲测有效的解决办法:改用Crontab
放弃/etc/profile那套,换成crontab来做开机自启,步骤超简单:
- 打开crontab的编辑界面:
crontab -e - 在文件最后加一行,指定开机启动你的脚本:
@reboot sudo python3 /home/pi/你的脚本实际路径/main.py & - 保存退出就行,crontab会自动生效
这样配置后,系统会等所有初始化(包括网络)都完成后再执行脚本,MQTT连接就能稳定建立了,完美解决之前的断连循环问题。
内容的提问来源于stack exchange,提问作者Giulio
相关产品推荐
相关产品推荐

