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

树莓派后台运行的Python温感上传InfluxDB脚本随机停止问题

问题根因分析
  • 脚本异常捕获缺失:现有代码仅捕获了键盘中断信号,网络波动、串口临时断开、InfluxDB服务不可用等场景都会触发未捕获异常,直接导致进程终止
  • cron配置错误:你填写的* * * * *是每分钟执行一次,并非每小时执行;且配置中未做重复运行校验,多次启动会导致串口被占用,同时cron默认环境变量可能缺失screen、Python的执行路径,也会导致命令执行失败
  • screen不是可靠的后台托管方案:screen会话会被系统资源限制、会话回收机制意外终止,本身没有自动重启能力,不适合长期运行的后台服务
修复步骤

1. 优化Python脚本稳定性

在原有代码基础上补充通用异常捕获,避免偶发错误直接终止进程,修改后的核心逻辑如下:

#!/usr/bin/python
# 原有导入部分新增time模块
import ConfigParser
import serial
import os, sys
import requests
import datetime
import optparse
import time # 新增导入


if __name__ == "__main__":
        parser = optparse.OptionParser(usage="%prog [-d] [--version]", version = "prog 1.2.0")
        parser.add_option('-d', '--debug', dest='debug', default=False, action='store_true',)
        options, remainder = parser.parse_args()

        c = ConfigParser.ConfigParser()
        c.read("/etc/gateway.conf")

        baud = c.getint('system','baud')
        serial_port = c.get('system', 'port')
        if not os.path.exists(serial_port):
                print 'Serial port %s not found' % serial_port
                sys.exit()
        ser = serial.Serial(serial_port, baud)

        DayOfMonth = datetime.datetime.utcnow().day
        ls_fileopen = False

        while True:
                try:
                        data_in = ser.readline()

                        utcnow = datetime.datetime.utcnow()
                        timestamp = utcnow.strftime("%s")

                        if options.debug: print data_in

                        while data_in[-1] in ['\r', '\n']:
                                data_in = data_in[:-1]

                        z = data_in.split(' ')
                        csv = ','.join(z[1:])
                        for sect in c.sections():
                                if sect=='emoncms' and c.getboolean(sect,'enabled'):
                                #EMONCMS
                                        hostname = c.get(sect, 'hostname')
                                        node = c.get(sect, 'node')
                                        apikey = c.get(sect, 'apikey')
                                        url = "http://%s/input/post?apikey=%s&node=%s&csv=%s" % (hostname, apikey, node, csv)
                                        if options.debug: print url
                                        r = requests.post(url, timeout=10) # 新增超时设置避免永久挂起
                                        if options.debug: print r
                                if sect=='influxdb' and c.getboolean(sect,'enabled'):
                              #INFLUXDB
                                        t = timestamp + '000000000'     
                                        url = c.get(sect, 'url')
                                        dbname = c.get(sect, 'dbname')
                                        user = c.get(sect, 'user')
                                        passwd = c.get(sect, 'passwd')
                                        measurement = c.get(sect, 'measurement')
                                        params = {'db': dbname, 'u': user, 'p': passwd}

                                        i = 0
                                        payload = ""
                                        for zz in z[1:]:
                                                i += 1
                                                if zz!="":
                                                        payload += "%s,channel=%02d value=%s %s\n" % (measurement, i, zz,t)
                                        if options.debug: print payload
                                        r = requests.post(url, params=params, data=payload, timeout=10) # 新增超时设置
                                        if options.debug: print r.text

                                if sect=='localsave' and c.getboolean(sect,'enabled'):
                              # LOCALSAVE     
                                        ls_dir = c.get(sect, 'directory')
                                        filename = ls_dir+'/'+timestamp+'.csv'
                                        if not ls_fileopen:
                                                f = open(filename,'w')
                                                ls_fileopen = True      
                                        if DayOfMonth != utcnow.day:
                                                DayOfMonth = utcnow.day
                                                if ls_fileopen: f.close()
                                                f = open(filename,'w')
                                                ls_fileopen = True

                                        f.write(timestamp+','+csv+'\n')


                except KeyboardInterrupt:
                        if ls_fileopen: f.close()
                        print "Terminating."
                        break
                # 新增通用异常捕获,出错后自动重试
                except Exception as e:
                        print "[%s] Run error: %s" % (datetime.datetime.utcnow(), str(e))
                        time.sleep(10)
                        # 尝试重置串口连接
                        try:
                            ser.close()
                            ser = serial.Serial(serial_port, baud)
                        except:
                            pass

修改完成后给脚本加执行权限:chmod +x /home/pi/lcl-gateway.py

2. 用systemd托管后台服务(推荐方案)

systemd是树莓派默认自带的进程管理工具,支持崩溃自动重启、开机自启,比screen更稳定可靠。
执行sudo nano /etc/systemd/system/lcl-gateway.service创建服务配置文件,写入以下内容:

[Unit]
Description=LCL Temperature Gateway Service
After=network.target

[Service]
User=pi
WorkingDirectory=/home/pi
ExecStart=/usr/bin/python /home/pi/lcl-gateway.py
Restart=always
RestartSec=10
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=lcl-gateway

[Install]
WantedBy=multi-user.target

保存退出后执行以下命令启用服务:

  • sudo systemctl daemon-reload
  • sudo systemctl enable lcl-gateway
  • sudo systemctl start lcl-gateway

后续可以用systemctl status lcl-gateway查看服务状态,journalctl -u lcl-gateway -f查看运行日志。

3. 若坚持使用cron的正确配置

每小时执行的cron表达式为0 * * * *,需要先校验进程是否存在,避免重复启动,执行sudo crontab -e写入以下配置:

0 * * * * /usr/bin/pgrep -f "lcl-gateway.py" > /dev/null || /usr/bin/screen -d -m /usr/bin/python /home/pi/lcl-gateway.py

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 15:24:02