如何重启出错的FFmpeg RTSP转RTMP进程并解决无法终止问题
解决FFmpeg RTSP转RTMP自动重启脚本无法终止的问题
问题分析
原脚本的while true; do $cmd && break; done逻辑会在FFmpeg进程退出(无论正常还是异常)时立刻重启,且未处理终止信号:
- 如果仅杀死FFmpeg子进程,父脚本会检测到执行失败,立即启动新的FFmpeg进程,导致“无法终止”的假象
- 若直接杀死脚本进程,
kill -9虽然能强制终止,但脚本没有机会清理子进程,可能残留FFmpeg进程
改进后的脚本
使用信号捕获机制,让脚本能够响应终止指令,同时清理子进程:
#!/bin/bash # 定义终止信号处理函数 cleanup() { echo "收到终止信号,正在停止FFmpeg进程..." if [ -n "$FFMPEG_PID" ]; then kill -9 "$FFMPEG_PID" 2>/dev/null wait "$FFMPEG_PID" 2>/dev/null fi exit 0 } # 捕获SIGINT(Ctrl+C)和SIGTERM(kill命令)信号 trap cleanup SIGINT SIGTERM # 检查参数是否齐全 if [ $# -ne 2 ]; then echo "用法: $0 <RTSP源地址> <RTMP推流地址>" exit 1 fi # 循环执行FFmpeg,直到正常退出或收到终止信号 while true; do # 启动FFmpeg并后台运行,记录PID ffmpeg -re -rtsp_transport tcp -i "$1" -c:v copy -c:a aac -ar 44100 -ac 1 -f flv -flvflags no_duration_filesize "$2" & FFMPEG_PID=$! # 等待FFmpeg进程结束,获取退出码 wait "$FFMPEG_PID" EXIT_CODE=$? # 如果是正常退出(码0),则终止循环 if [ $EXIT_CODE -eq 0 ]; then echo "FFmpeg正常退出,结束脚本" break fi # 异常退出则打印日志并重启 echo "FFmpeg异常退出(码$EXIT_CODE),10秒后重启..." sleep 10 done
关键改进点
- 信号捕获:通过
trap命令监听SIGINT和SIGTERM信号,收到信号时调用cleanup函数杀死FFmpeg子进程并退出脚本 - 进程管理:记录FFmpeg的PID,确保终止时能清理子进程
- 参数安全:直接使用位置参数
$1、$2并加引号,避免参数含空格时解析错误 - 退出码判断:仅当FFmpeg正常退出(退出码0)时才终止循环,异常退出自动重启
- 延迟重启:添加
sleep 10避免频繁重启导致资源占用过高
正确终止方法
- 前台运行时:直接按
Ctrl+C,脚本会自动清理FFmpeg进程并退出 - 后台运行时:
- 先找到脚本的PID:
ps aux | grep 脚本名.sh | grep -v grep - 发送终止信号:
kill <脚本PID>(推荐)或kill -9 <脚本PID>(强制终止)
- 先找到脚本的PID:
额外建议
- 可以添加日志输出到文件,方便排查FFmpeg异常退出原因:在FFmpeg命令后追加
>> /var/log/ffmpeg_rtsp2rtmp.log 2>&1 - 若FFmpeg频繁异常退出,建议先排查RTSP源稳定性或推流地址的网络问题,从根源解决重启需求
内容的提问来源于stack exchange,提问作者Samsul Islam
相关产品推荐
相关产品推荐

