Python脚本后台运行时进程停止问题:subprocess调用ffmpeg相关原因分析与修复方案咨询
后台运行Python脚本时subprocess子进程导致进程暂停的原因与修复方案
为什么会出现进程停止的情况?
当你用./download_vod.py &把脚本放到后台运行时,背后的核心原因是Unix-like系统对后台进程访问终端输入的限制:
- 后台进程默认会继承父shell的stdin(也就是终端),但系统不允许后台进程从终端读取输入——一旦尝试这么做,内核就会给进程发送
SIGTTIN信号,进程的默认行为就是被暂停,这就是你看到[1]+ Stopped download_vod.py的原因。 - 你的代码里,
subprocess.Popen没有明确处理子进程的stdin,再加上用了shell=True启动ffmpeg:shell进程会继承Python脚本的stdin关联,如果ffmpeg在执行过程中(比如某些默认交互逻辑、输入异常时)尝试读取stdin,就会触发SIGTTIN,导致整个进程组被暂停。 - 而前台运行时,进程可以正常访问终端stdin,自然不会触发这个信号,所以运行完全正常。
如何修复这个问题?
这里有几种可靠的解决方法,按推荐程度排序:
1. 重定向子进程的stdin到/dev/null(最直接的代码修改)
修改subprocess.Popen的参数,明确让子进程从/dev/null读取输入,彻底避免它尝试访问终端:
proc = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.DEVNULL, # 新增这一行,让子进程的stdin指向空设备 shell=True )
这样不管ffmpeg有没有尝试读取stdin,都会从/dev/null获取输入(永远读不到内容),不会触发SIGTTIN信号。
2. 避免使用shell=True(更安全且规范)
shell=True不仅有命令注入的安全风险(如果url或filename包含特殊字符,可能会被shell解析成恶意命令),还会额外启动一个shell进程,增加stdin关联的复杂度。建议改用命令列表的方式调用subprocess,同时处理stdin:
#!/usr/bin/python import subprocess url = "xxx" # 替换为实际URL filename = "xxx.mp4" # 替换为实际文件名 # 用列表传递命令参数,不需要手动加引号,避免shell解析问题 cmd = [ "ffmpeg", "-i", url, "-c:v", "copy", "-c:a", "copy", filename ] proc = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.DEVNULL # 同样重定向stdin到空设备 ) proc.wait()
这种方式更符合Python subprocess的最佳实践,也从根源上避免了shell层带来的stdin问题。
3. 启动脚本时重定向stdin(无需修改代码)
如果不想改动Python脚本,也可以在后台启动时直接把整个脚本的stdin重定向到/dev/null:
./download_vod.py < /dev/null &
这样Python脚本的stdin就指向了空设备,子进程也会继承这个设置,不会尝试读取终端输入,自然不会被暂停。
内容的提问来源于stack exchange,提问作者Jong Kyu Kim
相关产品推荐
相关产品推荐

