#!/bin/bash # RTSP网络连接诊断脚本 set -e # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color print_info() { echo -e "${GREEN}[INFO]${NC} $1" } print_warn() { echo -e "${YELLOW}[WARN]${NC} $1" } print_error() { echo -e "${RED}[ERROR]${NC} $1" } # 从配置文件读取RTSP URLs get_rtsp_urls() { if [[ -f "config.json" ]]; then # 使用jq解析JSON(如果可用) if command -v jq &> /dev/null; then jq -r '.streams[].rtsp_url' config.json else # 简单的grep解析 grep -o '"rtsp://[^"]*"' config.json | sed 's/"//g' fi else print_error "配置文件 config.json 不存在" exit 1 fi } # 测试网络连通性 test_network_connectivity() { local url=$1 print_info "测试RTSP URL: $url" # 解析URL获取主机和端口 local host=$(echo $url | sed -n 's|rtsp://\([^:]*\):\([0-9]*\)/.*|\1|p') local port=$(echo $url | sed -n 's|rtsp://\([^:]*\):\([0-9]*\)/.*|\2|p') if [[ -z "$host" || -z "$port" ]]; then print_error "无法解析RTSP URL: $url" return 1 fi print_info "主机: $host, 端口: $port" # DNS解析测试(改进的检测方法) print_info "测试DNS解析..." local dns_result=$(nslookup $host 2>/dev/null | grep -A 1 "Name:" | grep "Address:" | awk '{print $2}' | head -1) if [[ -z "$dns_result" ]]; then # 尝试使用dig命令 dns_result=$(dig +short $host 2>/dev/null | head -1) fi if [[ -z "$dns_result" ]]; then # 尝试使用host命令 dns_result=$(host $host 2>/dev/null | awk '{print $NF}' | head -1) fi if [[ -n "$dns_result" && "$dns_result" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then print_info "✅ DNS解析成功" print_info "解析IP: $dns_result" else print_error "❌ DNS解析失败" print_info "调试信息: nslookup输出:" nslookup $host 2>&1 | sed 's/^/ /' return 1 fi # 端口连通性测试(增强版) print_info "测试端口连通性..." # 尝试多种连接方法 local connection_success=false # 方法1: 使用nc (netcat) if command -v nc >/dev/null 2>&1; then if timeout 10 nc -z $host $port 2>/dev/null; then print_info "✅ 端口 $port 可达 (nc测试)" connection_success=true fi fi # 方法2: 使用telnet if [[ "$connection_success" == "false" ]] && command -v telnet >/dev/null 2>&1; then if timeout 10 bash -c "echo '' | telnet $host $port" 2>/dev/null | grep -q "Connected"; then print_info "✅ 端口 $port 可达 (telnet测试)" connection_success=true fi fi # 方法3: 使用/dev/tcp (bash内置) if [[ "$connection_success" == "false" ]]; then if timeout 10 bash -c "exec 3<>/dev/tcp/$host/$port && exec 3<&-" 2>/dev/null; then print_info "✅ 端口 $port 可达 (bash TCP测试)" connection_success=true fi fi if [[ "$connection_success" == "false" ]]; then print_error "❌ 端口 $port 不可达" print_info "详细诊断:" print_info " - 尝试ping主机: $(ping -c 1 -W 5 $host >/dev/null 2>&1 && echo '成功' || echo '失败')" print_info " - 尝试traceroute: $(command -v traceroute >/dev/null && echo '可用' || echo '不可用')" if command -v traceroute >/dev/null 2>&1; then print_info "路由跟踪 (前3跳):" timeout 10 traceroute -m 3 $host 2>/dev/null | head -4 | sed 's/^/ /' || echo " traceroute失败" fi return 1 fi # RTSP协议测试(简化版) print_info "测试RTSP协议响应..." if command -v nc >/dev/null 2>&1; then local rtsp_response=$(timeout 5 bash -c "echo -e 'OPTIONS $url RTSP/1.0\r\nCSeq: 1\r\nUser-Agent: Network-Test\r\n\r\n' | nc $host $port 2>/dev/null" || echo "") if [[ "$rtsp_response" == *"RTSP/1.0"* ]]; then print_info "✅ RTSP服务器响应正常" print_info "服务器响应: $(echo "$rtsp_response" | head -1 | tr -d '\r\n')" return 0 else print_warn "⚠️ 端口可达但RTSP服务可能异常" print_info "尝试的RTSP请求无响应,可能是:" print_info " 1. RTSP服务器需要认证" print_info " 2. 服务器配置了特殊的连接要求" print_info " 3. 端口上运行的不是RTSP服务" return 0 # 端口可达就认为基本连接正常 fi else print_info "✅ 基本连接测试通过(无法进行RTSP协议测试)" return 0 fi } # 主函数 main() { echo "" print_info "==========================================" print_info "RTSP网络连接诊断工具" print_info "==========================================" echo "" # 检查必要工具 for tool in nc nslookup timeout; do if ! command -v $tool &> /dev/null; then print_error "缺少必要工具: $tool" print_info "请安装: apt-get install netcat-openbsd dnsutils coreutils" exit 1 fi done # 显示网络环境信息 print_info "网络环境信息:" echo " 主机名: $(hostname)" echo " 网络接口: $(ip route get 8.8.8.8 | awk '{print $5; exit}')" echo " 外网IP检测: $(timeout 5 curl -s ifconfig.me || echo "无法获取")" echo " DNS配置:" cat /etc/resolv.conf | grep nameserver | head -3 | sed 's/^/ /' echo "" # 获取RTSP URLs print_info "从配置文件读取RTSP流地址..." local urls=($(get_rtsp_urls)) if [[ ${#urls[@]} -eq 0 ]]; then print_error "配置文件中未找到RTSP URL" exit 1 fi print_info "找到 ${#urls[@]} 个RTSP流地址" echo "" # 测试每个URL local success_count=0 local total_count=${#urls[@]} for url in "${urls[@]}"; do print_info "========== 测试流 $((success_count + 1))/$total_count ==========" if test_network_connectivity "$url"; then ((success_count++)) print_info "✅ 测试通过" else print_error "❌ 测试失败" fi echo "" done # 显示总结 print_info "==========================================" print_info "测试完成" print_info "==========================================" print_info "成功: $success_count/$total_count" if [[ $success_count -eq $total_count ]]; then print_info "🎉 所有RTSP流连接测试通过!" print_info "如果Docker中仍无法连接,请检查:" print_info " 1. Docker网络模式是否为host" print_info " 2. 容器内DNS配置是否正确" print_info " 3. 防火墙设置是否阻止连接" else print_warn "⚠️ 部分RTSP流连接失败" print_info "建议检查:" print_info " 1. 网络连接状态" print_info " 2. RTSP服务器状态" print_info " 3. 防火墙配置" fi echo "" } # 执行主函数 main