subprocess.terminate()无法终止shell=True启动的命令进程如何解决
问题原因
shell=True参数导致信号无法传递到目标进程:使用shell=True启动子进程时,Python实际创建的子进程是系统shell(如bash),你写的gst-launch命令是这个shell进程的子进程。terminate()方法只会给shell进程发送SIGTERM信号,而默认情况下shell不会主动把信号转发给它的子进程,所以真正执行任务的gst-launch进程会继续运行。- 阻塞导致无法打印终止日志:如果你的代码中在
terminate()之后调用了wait()方法等待进程退出,因为gst-launch进程一直没有终止,wait()会一直处于阻塞状态,后续的print("terminated")自然不会执行。
解决方案
方案1:移除shell=True,用列表形式传递命令(推荐)
直接将gst命令拆分为参数列表传递给Popen,Python会直接启动gst-launch-1.0作为子进程,没有中间shell层,terminate()可以直接将信号发送给目标进程:
import subprocess pipeline = [ "gst-launch-1.0", "nvcompositor", "name=comp", "sink_0::xpos=0", "sink_0::ypos=0", "sink_0::width=2560", "sink_0::height=720", "sink_0::zorder=1", "sink_0::alpha=1", "sink_1::xpos=0", "sink_1::ypos=0", "sink_1::width=2560", "sink_1::height=720", "sink_1::zorder=2", "sink_1::alpha=0.1", "!", "video/x-raw(memory:NVMM),format=RGBA", "!", "nv3dsink", "v4l2src", "device=/dev/video2", "!", "video/x-raw,format=YUY2,width=2560,height=720,framerate=30/1", "!", "nvvidconv", "!", "video/x-raw(memory:NVMM),format=RGBA", "!", "comp.sink_0", "videotestsrc", "!", "videoconvert", "!", "video/x-raw,format=RGBA", "!", "nvvidconv", "!", "video/x-raw(memory:NVMM),format=RGBA,width=2560,height=720", "!", "comp.sink_1" ] camera = subprocess.Popen(pipeline, shell=False) # 你的业务逻辑,等待终止触发条件 camera.terminate() # 等待进程确认退出,避免产生僵尸进程 camera.wait() print("terminated")
方案2:保留shell=True时,终止整个进程组
如果必须使用shell=True(比如命令中用到了shell专属的管道、通配符、变量替换等特性),可以在启动进程时创建独立进程组,终止时给整个进程组发信号:
import os import signal import subprocess pipeline = "你的原gst-launch命令字符串" # 启动时指定创建新会话,即新的进程组 camera = subprocess.Popen(pipeline, shell=True, start_new_session=True) # 你的业务逻辑,等待终止触发条件 # 给整个进程组发送SIGTERM信号,同时终止shell和它的所有子进程 os.killpg(os.getpgid(camera.pid), signal.SIGTERM) camera.wait() print("terminated")
补充说明
如果以上操作后gst-launch进程依然没有退出,可以将信号类型替换为signal.SIGKILL强制终止进程,不过强制终止可能导致GStreamer占用的硬件、内存资源没有正常释放,非必要不推荐使用。
内容的提问来源于stack exchange,提问作者Chealsie
相关产品推荐
相关产品推荐

