Python3 subprocess.Popen 为什么会创建两个进程呢?

开发环境:ubuntu14.0.4

python 版本: 3.6 执行如下方法

cmd = 'ffmpeg -i "http://60.171.135.231:86/pag/60.171xxxxxxxxxxxxxxxx" -f hls -vcodec copy -y /var/lib/xxx.m3u8 '
ps = subprocess.Popen(cmd, stdin=None, stdout=None, stderr=subprocess.PIPE, shell=True)

会创建两个进程,如下。这是为什么呢? subprocess.Popen 不是只会创建一个进程吗?

root[@VM-46047ef0-5d57-439c-b357-2f8e6f0be418](/user/VM-46047ef0-5d57-439c-b357-2f8e6f0be418):/var/lib/docker/rtsp2m3u8/qianshan01# ps aux | grep ffmpeg 
root     112225  0.0  0.0   4456   760 pts/4    S+   00:30   0:00 /bin/sh -c ffmpeg -i "http://60.171.135.231:86/pag/60.171.135.231/7302/001175/0/SUB/TCP/live.m3u8" -fflags flush_packets -max_delay 2 -reset_timestamps 1 -flags -global_header -hls_time 2 -hls_list_size 10 -f hls -hls_flags delete_segments -use_localtime 1 -vcodec copy -y /var/lib/docker/rtsp2m3u8/qianshan01/qianshan01.m3u8
root     112227  0.0  0.0  91928 13348 pts/4    S+   00:30   0:00 ffmpeg -i http://60.171.135.231:86/pag/60.171.135.231/7302/001175/0/SUB/TCP/live.m3u8 -fflags flush_packets -max_delay 2 -reset_timestamps 1 -flags -global_header -hls_time 2 -hls_list_size 10 -f hls -hls_flags delete_segments -use_localtime 1 -vcodec copy -y /var/lib/docker/rtsp2m3u8/qianshan01/qianshan01.m3u8
root     112291  0.0  0.0  12156  2216 pts/2    R+   00:30   0:00 grep --color=auto ffmpeg 

在执行ps.kill()或者ps.terminate()方法时,只能杀死进程 112225,进程 112227 仍然存在,这该如何解决呢?

尝试过,在subprocess.Popen()中增加,preexec_fn=os.setsid参数,但是在之后执行ps.kill()或者ps.terminate()方法时,依然只能杀死第一个进程。


Python3 subprocess.Popen 为什么会创建两个进程呢?

5 回复

shell=False 试试


我遇到过类似的情况。subprocess.Popen 本身只创建一个子进程,但如果你看到两个进程,通常是因为你启动的程序本身又创建了子进程。

最常见的情况是在 Windows 上使用 shell=True 参数。比如:

import subprocess
import time

# 这会创建两个进程:cmd.exe 和你的命令进程
proc = subprocess.Popen('ping 127.0.0.1 -n 5', shell=True)
proc.wait()

在 Windows 上,shell=True 会先启动 cmd.exe,然后 cmd.exe 再启动你的命令,所以你会看到两个进程。

在 Unix/Linux 上,如果你启动的是一个 shell 脚本或者程序自己 fork 了子进程,也会看到多个进程。

检查方法:

import subprocess
import psutil  # 需要安装 psutil

proc = subprocess.Popen(['python', '-c', 'import time; time.sleep(10)'])
parent = psutil.Process(proc.pid)
children = parent.children(recursive=True)
print(f"子进程数量: {len(children)}")

如果你不想有多余的进程,可以:

  1. 避免使用 shell=True(除非必要)
  2. 使用 exec 替换当前进程(在 Unix 上)
  3. 确保你启动的程序不会自己创建子进程

检查下你是不是用了 shell=True 或者在启动一个会创建子进程的程序。

shell=True就是sh -c啊.

顺便说下 14.04 该升级了吧…

谢谢各位了,已经找到问题了。一开始用的 mac 环境,使用 shell=True 参数,subprocess.Popen()只会产生一个进程。部署到线上 linux 服务器上后,就一直是两个进程。
现已解决:
修改 shell=False, 并且 args 参数使用列表的形式,将命令拼接起来,执行就好了。

回到顶部