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

求助:Bash while循环中ffmpeg无法随动态URL变量更新启停

动态更新URL并控制ffmpeg启停的Bash脚本修复

需求说明

  • 通过journalctl监听"application"的日志,提取其中的目标URL(var0)
  • 根据var0的状态执行对应逻辑:
    1. URL未变化:不执行任何操作
    2. URL已变更:终止运行中的ffmpeg,使用新URL重启推流
    3. URL为空:终止运行中的ffmpeg,等待新的URL出现
  • 最终通过ffmpeg将分离的音视频HLSv5流合并为MPEG-TS格式,推送到udp://227.0.0.1:1234

当前问题

脚本首次启动时逻辑正常,但当var0变更或为空时,仍会沿用首次启动的URL执行ffmpeg,无法按预期完成启停控制。

原脚本

#!/bin/sh

journalctl -fu application -o cat > /tmp/jctl &

while true
do
  cat /tmp/jctl | grep "playing" | tail -n1 | tee /tmp/all

  grep -Eo "(prox/http|prox/https)%3a//\[a-zA-Z0-9./?=\_%:-\]\*(:)" /tmp/all |
    tail -n1 | sed 's,:,,g' | sed 's,prox/https%3a,https:,g' | tee /tmp/var0

  var0=$(sed -n "1p" /tmp/var0)
  if [ ! -z "$var0" ] # URL not empty
  then
    curl -L $var0 | tee /tmp/tmp
    var1=$(sed -n '/RESOLUTION=1/{n;p}' /tmp/tmp | sed -n "1p")
    var2=$(sed '/DEFAULT=YES[^[]*URI="/!d;s//&\n/;s/.*\n//;:a;/"/bb;$!{n;ba};:b;s//\n&/;P;D' /tmp/tmp | sed -n "1p")
    `ffmpeg -re -rtbufsize 8M -i $var1 -i $var2 -c copy -f mpegts udp://227.0.0.1:1234?pkt_size=1316 &`
  fi
done  

修复后的脚本

#!/bin/bash

# 初始化状态变量
old_var0=""
ffmpeg_pid=""
# 定义临时文件列表,方便统一清理
temp_files="/tmp/jctl /tmp/all /tmp/var0 /tmp/tmp"

# 脚本退出时的清理逻辑
cleanup() {
  # 终止ffmpeg进程(如果存在)
  [ -n "$ffmpeg_pid" ] && kill "$ffmpeg_pid" 2>/dev/null
  # 删除临时文件
  rm -f $temp_files
  exit 0
}
# 捕获退出、中断、终止信号,触发清理
trap cleanup EXIT INT TERM

# 启动journalctl实时监听日志,后台运行
journalctl -fu application -o cat > /tmp/jctl &

while true
do
  # 只读取新增的日志行,避免重复处理历史内容
  tail -n0 -F /tmp/jctl | grep -m1 "playing" | tee /tmp/all

  # 修正正则,正确提取并格式化URL
  grep -Eo "(prox/http|prox/https)%3a//[a-zA-Z0-9./?=\_%:-]*" /tmp/all |
    tail -n1 | sed 's,prox/http%3a,http:,g' | sed 's,prox/https%3a,https:,g' | tee /tmp/var0

  var0=$(cat /tmp/var0 | tr -d '\n')

  # 情况3:URL为空,终止ffmpeg并重置状态
  if [ -z "$var0" ]; then
    [ -n "$ffmpeg_pid" ] && kill "$ffmpeg_pid" 2>/dev/null
    ffmpeg_pid=""
    old_var0=""
    continue
  fi

  # 情况1:URL未变化,直接跳过循环
  if [ "$var0" = "$old_var0" ]; then
    continue
  fi

  # 情况2:URL已变更,先终止旧的ffmpeg进程
  [ -n "$ffmpeg_pid" ] && kill "$ffmpeg_pid" 2>/dev/null

  # 获取音视频流地址,简化sed逻辑
  curl -L "$var0" | tee /tmp/tmp
  var1=$(sed -n '/RESOLUTION=1/{n;p}' /tmp/tmp | head -n1)
  var2=$(sed -n '/DEFAULT=YES/{s/.*URI="\([^"]*\)".*/\1/p}' /tmp/tmp | head -n1)

  # 启动新的ffmpeg进程并记录PID
  ffmpeg -re -rtbufsize 8M -i "$var1" -i "$var2" -c copy -f mpegts udp://227.0.0.1:1234?pkt_size=1316 &
  ffmpeg_pid=$!
  # 更新旧URL记录
  old_var0="$var0"
done

关键修改说明

  • 进程管控:新增ffmpeg_pid变量记录进程ID,确保能精准终止旧的ffmpeg实例
  • URL对比:用old_var0保存上一次的有效URL,避免重复启动相同推流任务
  • 空URL处理:明确判断URL为空时的逻辑,终止ffmpeg并重置状态
  • 日志读取优化:改用tail -n0 -F仅读取新增日志行,避免每次循环重复处理历史内容
  • 正则修正:修复原URL提取正则的语法错误,确保能正确匹配目标URL
  • 安全加固:给变量添加双引号,避免含特殊字符的URL导致命令执行异常
  • 清理机制:新增退出清理逻辑,脚本终止时自动删除临时文件、终止子进程
  • 逻辑简化:简化var2的提取sed命令,提升可读性和稳定性

内容的提问来源于stack exchange,提问作者NewbiDam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 04:10:30