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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 04:27:52