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

使用sudo运行含ping3的Python脚本立即退出的原因及解决方案咨询

问题描述

我编写了一个使用ping3库执行服务器ping检测的Python脚本,由于该功能需要root权限,因此用sudo运行。但发现不使用sudo时脚本可正常保持运行状态,使用sudo运行则立即退出且无任何异常抛出。脚本代码如下:

import atexit
import RPi.GPIO as gpio
import sys
import time
from threading import Thread

import ping3
from ping3 import ping
from phue import Bridge
from datetime import datetime

ping3.EXCEPTIONS = False

functionOne = 13
functionTwo = 15
functionThree = 16
relaisStörung = 18

functionOneState = False
functionTwoState = False
errorState = False


def handleExit():
    gpio.cleanup()
    print('EXITED! ', hueLogic.getCurrentDateTime())
    sys.exit(0)


class NetworkWatchdog(Thread):

    def __init__(self):
        # Call the Thread class's init function
        Thread.__init__(self)

    def run(self):
        global errorState
        routerAddress = '192.168.178.1'
        errorCounter = 0
        while 1:
            result = ping(routerAddress)
            if not result or result is None:
                errorCounter = + 1
            else:
                errorCounter = 0
            if errorCounter > 1:
                print('Netzwerk Fehler! Stör Relay an! ', hueLogic.getCurrentDateTime())
                errorState = True
                gpio.output(relaisStörung, gpio.HIGH)
            elif errorCounter < 1:
                if errorState:
                    print("Netzwerk Fehler behoben! Stör Relay normal! ", hueLogic.getCurrentDateTime())
                    errorState = False
                    gpio.output(relaisStörung, gpio.LOW)
            time.sleep(2)



# sys.stdout = open('/home/admin/Desktop/log.log', 'a+')
# sys.stderr = open('/home/admin/Desktop/log.log', 'a+')
atexit.register(handleExit)
hueLogic = HueLogic()
watchDog = NetworkWatchdog()
watchDog.daemon = True
watchDog.start()
print("--------------------------------")
print("Programm started! ", hueLogic.getCurrentDateTime())

gpio.setmode(gpio.BOARD)
gpio.setup(functionOne, gpio.IN, pull_up_down=gpio.PUD_DOWN)
gpio.setup(functionTwo, gpio.IN, pull_up_down=gpio.PUD_DOWN)
gpio.setup(functionThree, gpio.IN, pull_up_down=gpio.PUD_DOWN)
gpio.setup(relaisStörung, gpio.OUT)
# relais default on
gpio.output(relaisStörung, gpio.LOW)

gpio.add_event_detect(functionOne, gpio.BOTH, callback=hueLogic.functionOne, bouncetime=500)
gpio.add_event_detect(functionTwo, gpio.BOTH, callback=hueLogic.functionTwo, bouncetime=500)
gpio.add_event_detect(functionThree, gpio.BOTH, callback=hueLogic.functionThree, bouncetime=500)

现咨询该现象产生的原因,以及添加while True循环作为解决方案是否可行?


问题分析与解决方案

一、现象原因

核心问题出在守护线程特性和sudo环境下主线程的退出时机:

  1. 你将watchDog线程设为了守护线程(watchDog.daemon = True),这类线程的规则是:当所有非守护线程结束时,Python进程会直接终止,不管守护线程是否还在运行。
  2. 不使用sudo时,RPi.GPIO的add_event_detect会依赖底层系统事件循环让主线程保持活跃,不会立即退出,因此守护线程能正常运行。
  3. 使用sudo时,权限上下文或环境变量的变化,导致RPi.GPIO的事件检测无法维持主线程的阻塞状态,主线程执行完所有初始化代码后直接退出,守护线程被强制终止,进程随之结束,所以看不到异常——进程是被正常终止的。

另外代码里存在一个小bug:errorCounter = + 1应该写成errorCounter += 1,否则每次错误只会把计数器设为1,无法累加,会导致网络故障判断逻辑失效。

二、添加while True循环是否可行?

完全可行,这是解决该问题的简单有效方案:

  • 在脚本末尾添加如下代码,让主线程保持阻塞状态,不会提前退出,守护线程就能持续运行:
    while True:
        time.sleep(1)
    
  • 另一种替代方案是把watchDog.daemon设为False,这样即使主线程结束,只要该线程还在运行,进程就不会终止。不过这种方式需要注意线程的优雅退出逻辑,避免进程无法正常结束。

额外建议

  1. 修复errorCounter = +1的bug,改为errorCounter +=1,确保网络故障计数逻辑正常工作。
  2. 开启日志输出到文件的代码(你已注释的部分),方便排查sudo运行时的潜在问题,比如是否能正常加载phue库或访问GPIO引脚。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 13:17:02