install_local_test.sh 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. #!/usr/bin/env bash
  2. # 安装并本地联调测试:
  3. # 1. 构建并安装最新二进制到 /usr/local/bin/rtsp_multi_view
  4. # 2. 安装本地测试配置 /etc/rtsp_multi_view/channels_local.conf(若不存在)
  5. # 3. 临时停止系统服务(释放显示输出),用 PLC 模拟器跑若干 plc_sim 循环:
  6. # plc_server.py + plc_sim 写状态 + 已安装的 rtsp_multi_view 读布局,
  7. # 期间模拟一次 PLC 离线,验证右下角"PLC离线"报警与自动恢复
  8. # 4. 结束后自动恢复系统服务
  9. #
  10. # 用法: sudo ./install_local_test.sh [循环数] [每状态毫秒]
  11. # 循环数 plc_sim 完整循环次数(6 状态 x 间隔 = 1 循环),默认 1
  12. # 每状态毫秒 状态切换间隔,默认 5000
  13. # 环境变量: NO_OFFLINE=1 跳过 PLC 离线模拟
  14. set -u
  15. DIR="$(cd "$(dirname "$0")" && pwd)"
  16. cd "$DIR"
  17. BIN_SRC="$DIR/build/rtsp_multi_view"
  18. BIN_DST="/usr/local/bin/rtsp_multi_view"
  19. CONFIG_DIR="/etc/rtsp_multi_view"
  20. OUT="/tmp/opencode/install_local_test"
  21. CYCLE=1
  22. INTERVAL_MS=5000
  23. if [ $# -ge 1 ]; then CYCLE="$1"; fi
  24. if [ $# -ge 2 ]; then INTERVAL_MS="$2"; fi
  25. if [ "$CYCLE" -lt 1 ]; then CYCLE=1; fi
  26. if [ "$INTERVAL_MS" -lt 1000 ]; then INTERVAL_MS=1000; fi
  27. if [ "$EUID" -ne 0 ]; then
  28. echo "错误:请用 root 运行 (sudo ./install_local_test.sh)"
  29. exit 1
  30. fi
  31. PLCPID=""; SIMPID=""; VIEWPID=""
  32. SERVICE_ACTIVE=0
  33. stop_test_procs() {
  34. [ -n "$VIEWPID" ] && kill "$VIEWPID" 2>/dev/null
  35. [ -n "$SIMPID" ] && kill "$SIMPID" 2>/dev/null
  36. [ -n "$PLCPID" ] && kill "$PLCPID" 2>/dev/null
  37. sleep 1
  38. kill -9 "$VIEWPID" "$SIMPID" "$PLCPID" 2>/dev/null
  39. }
  40. cleanup() {
  41. stop_test_procs
  42. if [ "$SERVICE_ACTIVE" -eq 1 ]; then
  43. systemctl start rtsp_multi_view 2>/dev/null
  44. SERVICE_ACTIVE=0
  45. fi
  46. }
  47. trap cleanup EXIT INT TERM
  48. echo "== 构建 =="
  49. cmake --build "$DIR/build" -j"$(nproc)" || {
  50. echo "构建失败,请先运行 ./build.sh" >&2
  51. exit 1
  52. }
  53. echo "== 安装二进制 -> $BIN_DST =="
  54. cp "$BIN_SRC" "$BIN_DST"
  55. chmod +x "$BIN_DST"
  56. echo "== 安装本地测试配置 =="
  57. mkdir -p "$CONFIG_DIR"
  58. if [ ! -f "$CONFIG_DIR/channels_local.conf" ]; then
  59. cp "$DIR/channels_local.conf" "$CONFIG_DIR/channels_local.conf"
  60. echo "已创建 $CONFIG_DIR/channels_local.conf"
  61. else
  62. echo "已存在 $CONFIG_DIR/channels_local.conf(跳过)"
  63. fi
  64. if systemctl is-active --quiet rtsp_multi_view 2>/dev/null; then
  65. SERVICE_ACTIVE=1
  66. echo "== 临时停止系统服务 (rtsp_multi_view.service) =="
  67. systemctl stop rtsp_multi_view
  68. fi
  69. rm -rf "$OUT"; mkdir -p "$OUT"
  70. rm -f "$DIR/flog.txt"
  71. CONF="${CONF:-$DIR/channels_local.conf}"
  72. if ss -ltnp 2>/dev/null | grep -q ':102 '; then
  73. echo "错误:127.0.0.1:102 已被占用,无法启动本地 PLC:"
  74. ss -ltnp 2>/dev/null | grep ':102 '
  75. echo "请先释放端口(或 kill 占用进程)后重试。"
  76. exit 1
  77. fi
  78. echo "== 启动本地 PLC (plc_server.py :102) =="
  79. python3 "$DIR/plc_server.py" -p 102 >"$OUT/plcserver.log" 2>&1 &
  80. PLCPID=$!
  81. sleep 1
  82. if ! kill -0 "$PLCPID" 2>/dev/null || ! ss -ltnp 2>/dev/null | grep -q "pid=$PLCPID,"; then
  83. echo "错误:plc_server 启动失败,日志如下:"
  84. cat "$OUT/plcserver.log"
  85. exit 1
  86. fi
  87. echo "== 启动状态切换器 (plc_sim: ${CYCLE} 循环 x ${INTERVAL_MS}ms) =="
  88. "$DIR/build/plc_sim" -c "$CONF" -t "$INTERVAL_MS" >"$OUT/plcsim.log" 2>&1 &
  89. SIMPID=$!
  90. echo "== 启动已安装的主程序 ($BIN_DST) =="
  91. "$BIN_DST" -c "$CONF" >"$OUT/viewer.log" 2>&1 &
  92. VIEWPID=$!
  93. RUN_SEC=$(( CYCLE * 6 * INTERVAL_MS / 1000 + 10 ))
  94. OFF_SEC=$(( RUN_SEC / 2 > 8 ? RUN_SEC / 2 : 8 ))
  95. ONLINE_SEC=$(( OFF_SEC - 4 > 3 ? OFF_SEC - 4 : 3 ))
  96. echo "-- 等待 PLC 连通 (${ONLINE_SEC}s) --"
  97. sleep "$ONLINE_SEC"
  98. if [ "${NO_OFFLINE:-0}" != "1" ]; then
  99. echo "== 模拟 PLC 离线:杀掉 plc_server (${OFF_SEC}s) =="
  100. kill "$PLCPID" 2>/dev/null
  101. for _ in 1 2 3 4 5; do
  102. ss -ltnp 2>/dev/null | grep -q ':102 ' || break
  103. sleep 1
  104. done
  105. sleep "$OFF_SEC"
  106. echo "== 恢复 PLC =="
  107. python3 "$DIR/plc_server.py" -p 102 >>"$OUT/plcserver.log" 2>&1 &
  108. PLCPID=$!
  109. sleep 1
  110. if ! kill -0 "$PLCPID" 2>/dev/null || ! ss -ltnp 2>/dev/null | grep -q "pid=$PLCPID,"; then
  111. echo "错误:恢复 plc_server 失败,日志如下:"
  112. cat "$OUT/plcserver.log"
  113. exit 1
  114. fi
  115. fi
  116. echo "-- 跑完剩余时间 ($(( RUN_SEC - ONLINE_SEC - OFF_SEC ))s) --"
  117. sleep $(( RUN_SEC - ONLINE_SEC - OFF_SEC ))
  118. echo "== 停止本地测试进程 =="
  119. stop_test_procs
  120. if [ "$SERVICE_ACTIVE" -eq 1 ]; then
  121. echo "== 恢复系统服务 =="
  122. systemctl start rtsp_multi_view
  123. SERVICE_ACTIVE=0
  124. fi
  125. echo "==================== 结果 ===================="
  126. echo "--- PLC 报警/恢复 (flog.txt) ---"
  127. grep "PLC" "$DIR/flog.txt" 2>/dev/null || echo "(无 PLC 记录)"
  128. echo "--- plc_sim 状态循环 ---"
  129. grep -E "state [0-9]|connected" "$OUT/plcsim.log" | tail -20
  130. echo "--- viewer 异常 (排除常规超时重连) ---"
  131. grep -iE "error|fail|超时|失败" "$OUT/viewer.log" | grep -viE "连接失败: rtsp|Timeout waiting for first frame|connect 127.0.0.1:102 failed|recv failed" | head -10 || true
  132. echo "(done)"
  133. echo "完整日志: $OUT/"
  134. echo "生产服务: systemctl status rtsp_multi_view"