#!/usr/bin/env bash # 安装并本地联调测试: # 1. 构建并安装最新二进制到 /usr/local/bin/rtsp_multi_view # 2. 安装本地测试配置 /etc/rtsp_multi_view/channels_local.conf(若不存在) # 3. 临时停止系统服务(释放显示输出),用 PLC 模拟器跑若干 plc_sim 循环: # plc_server.py + plc_sim 写状态 + 已安装的 rtsp_multi_view 读布局, # 期间模拟一次 PLC 离线,验证右下角"PLC离线"报警与自动恢复 # 4. 结束后自动恢复系统服务 # # 用法: sudo ./install_local_test.sh [循环数] [每状态毫秒] # 循环数 plc_sim 完整循环次数(6 状态 x 间隔 = 1 循环),默认 1 # 每状态毫秒 状态切换间隔,默认 5000 # 环境变量: NO_OFFLINE=1 跳过 PLC 离线模拟 set -u DIR="$(cd "$(dirname "$0")" && pwd)" cd "$DIR" BIN_SRC="$DIR/build/rtsp_multi_view" BIN_DST="/usr/local/bin/rtsp_multi_view" CONFIG_DIR="/etc/rtsp_multi_view" OUT="/tmp/opencode/install_local_test" CYCLE=1 INTERVAL_MS=5000 if [ $# -ge 1 ]; then CYCLE="$1"; fi if [ $# -ge 2 ]; then INTERVAL_MS="$2"; fi if [ "$CYCLE" -lt 1 ]; then CYCLE=1; fi if [ "$INTERVAL_MS" -lt 1000 ]; then INTERVAL_MS=1000; fi if [ "$EUID" -ne 0 ]; then echo "错误:请用 root 运行 (sudo ./install_local_test.sh)" exit 1 fi PLCPID=""; SIMPID=""; VIEWPID="" SERVICE_ACTIVE=0 stop_test_procs() { [ -n "$VIEWPID" ] && kill "$VIEWPID" 2>/dev/null [ -n "$SIMPID" ] && kill "$SIMPID" 2>/dev/null [ -n "$PLCPID" ] && kill "$PLCPID" 2>/dev/null sleep 1 kill -9 "$VIEWPID" "$SIMPID" "$PLCPID" 2>/dev/null } cleanup() { stop_test_procs if [ "$SERVICE_ACTIVE" -eq 1 ]; then systemctl start rtsp_multi_view 2>/dev/null SERVICE_ACTIVE=0 fi } trap cleanup EXIT INT TERM echo "== 构建 ==" cmake --build "$DIR/build" -j"$(nproc)" || { echo "构建失败,请先运行 ./build.sh" >&2 exit 1 } echo "== 安装二进制 -> $BIN_DST ==" cp "$BIN_SRC" "$BIN_DST" chmod +x "$BIN_DST" echo "== 安装本地测试配置 ==" mkdir -p "$CONFIG_DIR" if [ ! -f "$CONFIG_DIR/channels_local.conf" ]; then cp "$DIR/channels_local.conf" "$CONFIG_DIR/channels_local.conf" echo "已创建 $CONFIG_DIR/channels_local.conf" else echo "已存在 $CONFIG_DIR/channels_local.conf(跳过)" fi if systemctl is-active --quiet rtsp_multi_view 2>/dev/null; then SERVICE_ACTIVE=1 echo "== 临时停止系统服务 (rtsp_multi_view.service) ==" systemctl stop rtsp_multi_view fi rm -rf "$OUT"; mkdir -p "$OUT" rm -f "$DIR/flog.txt" CONF="${CONF:-$DIR/channels_local.conf}" if ss -ltnp 2>/dev/null | grep -q ':102 '; then echo "错误:127.0.0.1:102 已被占用,无法启动本地 PLC:" ss -ltnp 2>/dev/null | grep ':102 ' echo "请先释放端口(或 kill 占用进程)后重试。" exit 1 fi echo "== 启动本地 PLC (plc_server.py :102) ==" python3 "$DIR/plc_server.py" -p 102 >"$OUT/plcserver.log" 2>&1 & PLCPID=$! sleep 1 if ! kill -0 "$PLCPID" 2>/dev/null || ! ss -ltnp 2>/dev/null | grep -q "pid=$PLCPID,"; then echo "错误:plc_server 启动失败,日志如下:" cat "$OUT/plcserver.log" exit 1 fi echo "== 启动状态切换器 (plc_sim: ${CYCLE} 循环 x ${INTERVAL_MS}ms) ==" "$DIR/build/plc_sim" -c "$CONF" -t "$INTERVAL_MS" >"$OUT/plcsim.log" 2>&1 & SIMPID=$! echo "== 启动已安装的主程序 ($BIN_DST) ==" "$BIN_DST" -c "$CONF" >"$OUT/viewer.log" 2>&1 & VIEWPID=$! RUN_SEC=$(( CYCLE * 6 * INTERVAL_MS / 1000 + 10 )) OFF_SEC=$(( RUN_SEC / 2 > 8 ? RUN_SEC / 2 : 8 )) ONLINE_SEC=$(( OFF_SEC - 4 > 3 ? OFF_SEC - 4 : 3 )) echo "-- 等待 PLC 连通 (${ONLINE_SEC}s) --" sleep "$ONLINE_SEC" if [ "${NO_OFFLINE:-0}" != "1" ]; then echo "== 模拟 PLC 离线:杀掉 plc_server (${OFF_SEC}s) ==" kill "$PLCPID" 2>/dev/null for _ in 1 2 3 4 5; do ss -ltnp 2>/dev/null | grep -q ':102 ' || break sleep 1 done sleep "$OFF_SEC" echo "== 恢复 PLC ==" python3 "$DIR/plc_server.py" -p 102 >>"$OUT/plcserver.log" 2>&1 & PLCPID=$! sleep 1 if ! kill -0 "$PLCPID" 2>/dev/null || ! ss -ltnp 2>/dev/null | grep -q "pid=$PLCPID,"; then echo "错误:恢复 plc_server 失败,日志如下:" cat "$OUT/plcserver.log" exit 1 fi fi echo "-- 跑完剩余时间 ($(( RUN_SEC - ONLINE_SEC - OFF_SEC ))s) --" sleep $(( RUN_SEC - ONLINE_SEC - OFF_SEC )) echo "== 停止本地测试进程 ==" stop_test_procs if [ "$SERVICE_ACTIVE" -eq 1 ]; then echo "== 恢复系统服务 ==" systemctl start rtsp_multi_view SERVICE_ACTIVE=0 fi echo "==================== 结果 ====================" echo "--- PLC 报警/恢复 (flog.txt) ---" grep "PLC" "$DIR/flog.txt" 2>/dev/null || echo "(无 PLC 记录)" echo "--- plc_sim 状态循环 ---" grep -E "state [0-9]|connected" "$OUT/plcsim.log" | tail -20 echo "--- viewer 异常 (排除常规超时重连) ---" 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 echo "(done)" echo "完整日志: $OUT/" echo "生产服务: systemctl status rtsp_multi_view"