Raspberry Pi 4下subprocess.Popen启动shell脚本终止失败及隐藏输出问题
错误原因
- 全局变量声明位置错误:
global关键字仅在函数内部生效,你在模块层级声明的global shellscript无效,subprocess_settings函数内赋值的shellscript属于局部变量,主逻辑和KeyboardInterrupt捕获块访问的全局shellscript始终未赋值,运行时会抛出NameError,导致进程终止逻辑失效。 - 输出隐藏逻辑错误:你注释的将
&> /dev/null作为Popen参数的写法无效,列表形式启动进程不会经过shell解析重定向符号,脚本输出仍会打印到终端。 - 进程清理不彻底:直接杀死shell脚本父进程的话,脚本内部启动的
modprobe、flirone子进程会变成孤儿进程继续运行,无法真正停止Flir驱动,同时subprocess.Popen.kill(shellscript)的写法冗余,不符合常规调用规范。 - 边界情况未处理:如果进程还未启动就触发键盘中断,直接调用kill方法会抛出未定义异常。
修复代码
Python代码修改
import sys import os import time import subprocess import signal shellscript = None # 提前初始化全局变量 def subprocess_settings(): global shellscript # 函数内部声明使用全局变量 # 重定向所有输出到DEVNULL,开启新会话方便后续清理整个进程组 shellscript = subprocess.Popen( ["/home/pi/Desktop/init_flir.sh"], close_fds=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT, start_new_session=True ) try: x = 1 while True: if x == 0: sys.exit() elif x == 1: print("Yas, x=1") time.sleep(2) subprocess_settings() time.sleep(5) print("Driver test is in background mode") time.sleep(2) print("Close process") # 杀死整个进程组,清理所有子进程 os.killpg(os.getpgid(shellscript.pid), signal.SIGTERM) shellscript.wait() # 等待进程退出避免僵尸进程 x=0 except KeyboardInterrupt: # 先判断进程是否存在再执行清理 if shellscript is not None and shellscript.poll() is None: os.killpg(os.getpgid(shellscript.pid), signal.SIGTERM) shellscript.wait()
配套shell脚本无需修改,保持原内容即可
#!/bin/bash cd /home/pi/github/flirone-v4l2 sudo modprobe v4l2loopback exclusive_caps=0,0 video_nr=1,2,3 sudo ./flirone ~/github/flirone-v4l2/palettes/Iron2.raw
效果验证
- 无终端输出:shell脚本所有标准输出、错误输出都被重定向到空设备,不会在终端打印任何内容
- 双终止逻辑生效:代码内部分支主动终止、Ctrl+C触发键盘中断终止两种逻辑都可以正常清理所有相关进程,无残留孤儿进程
- 兼容边界场景:提前触发键盘中断不会抛出未定义错误
内容的提问来源于stack exchange,提问作者Selenee
相关产品推荐
相关产品推荐

