Linux Shell启动后台ffmpeg不随脚本终止运行的实现方法
核心问题定位
原代码里的进程绑定问题本质是三个语法误用导致的,没有真正实现进程脱离:
nohup $(ffmpeg命令)是完全错误的写法。$(...)是命令替换语法,会先把括号里的ffmpeg跑一遍、把输出抓出来当字符串喂给nohup,真正运行的ffmpeg根本没被nohup接管,自然会跟着父脚本的信号退出。- 所有ffmpeg和script.sh属于同一个进程会话组,脚本被终端挂断、强杀时,整个组会收到连带的终止信号,ffmpeg无法幸免。
- 重复定义同名的
startFFMPEG函数,还把函数本身丢到后台运行,多余的进程层级进一步加强了和父脚本的绑定关系。
具体修正逻辑
要实现ffmpeg完全独立于脚本运行,只需要按三点调整:
- 删掉错误的命令替换嵌套,让进程隔离操作直接作用在ffmpeg可执行文件上。
- 给ffmpeg做完整的流脱绑:标准输入对接
/dev/null,输出和错误日志重定向到空设备或指定文件,切断和父脚本的输入输出关联。 - 用
setsid启动ffmpeg,直接给它创建独立的新会话,从进程组层面和父脚本完全隔离,哪怕脚本被SIGKILL强杀,ffmpeg也收不到连带的终止信号。
修正后的完整脚本
#!/bin/bash # 通用ffmpeg启动函数:接收输入地址、logo路径、输出文件三个参数 startFFMPEG() { local input_url=$1 local logo_path=$2 local output_file=$3 # 用setsid启动完全脱离会话的ffmpeg,重定向全链路流 setsid /root/bin/ffmpeg \ -i "$input_url" \ -i "$logo_path" \ outputcmd -y "$output_file" \ </dev/null >/dev/null 2>&1 } while xxxxxxx; do echo "RUN COMMAND1" # 第一组转码,三级fallback startFFMPEG "url" "/var/www/logo/logo.png" "1.m3u8" || \ startFFMPEG "url" "/var/www/logo/logo.png" "2.m3u8" || \ startFFMPEG "url" "/var/www/logo/logo.png" "3.m3u8" echo "RUN COMMAND 2" # 第二组转码,三级fallback startFFMPEG "url2" "/var/www/logo/logo.png" "11.m3u8" || \ startFFMPEG "url2" "/var/www/logo/logo.png" "12.m3u8" || \ startFFMPEG "url3" "/var/www/logo/logo.png" "13.m3u8" sleep 10 done
补充说明
- 原代码里
startFFMPEG &的写法没必要存在:函数内部已经把ffmpeg扔到后台运行了,再把函数本身丢后台只会增加一层多余的子进程,反而破坏隔离效果。 - 如果不想用
setsid,也可以用nohup 命令 &搭配脚本启动后执行disown -a,但这种方式对强杀整个进程组的场景防护能力弱,优先推荐用setsid做硬隔离。 - 重定向必须写在ffmpeg命令的同一层级,不能嵌套在命令替换里,否则流的关联关系切不断。
内容的提问来源于stack exchange,提问作者wuqn yqow
相关产品推荐
相关产品推荐

