#!/usr/bin/env bash # AGV GLB 一键启动(Linux / macOS) # 用法: # ./start.sh 启动服务并打开播放页 # ./start.sh --setup 首次部署:创建 .venv 并安装 requirements.txt # ./start.sh --no-browser 仅启动服务 set -euo pipefail ROOT="$(cd "$(dirname "$0")" && pwd)" cd "$ROOT" SETUP=0 NO_BROWSER=0 PORT="${PORT:-8765}" for arg in "$@"; do case "$arg" in --setup) SETUP=1 ;; --no-browser) NO_BROWSER=1 ;; -h|--help) echo "用法: ./start.sh [--setup] [--no-browser]" exit 0 ;; esac done step() { printf '>> %s\n' "$1"; } find_python() { for cmd in python3 python py; do if command -v "$cmd" >/dev/null 2>&1; then ver=$("$cmd" -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")' 2>/dev/null || true) major=${ver%%.*} minor=${ver#*.} if [ "$major" -gt 3 ] 2>/dev/null || { [ "$major" -eq 3 ] && [ "$minor" -ge 10 ]; }; then echo "$cmd" return 0 fi fi done return 1 } venv_python() { if [ -x "$ROOT/.venv/bin/python" ]; then echo "$ROOT/.venv/bin/python" fi } port_in_use() { if command -v ss >/dev/null 2>&1; then ss -ltn 2>/dev/null | grep -q ":${PORT} " elif command -v lsof >/dev/null 2>&1; then lsof -iTCP:"$PORT" -sTCP:LISTEN >/dev/null 2>&1 else return 1 fi } wait_ready() { local url="http://127.0.0.1:${PORT}/api/catalog" for _ in $(seq 1 75); do if curl -sf "$url" >/dev/null 2>&1; then return 0 fi sleep 0.4 done return 1 } open_browser() { local url="http://127.0.0.1:${PORT}/viewer/play.html" if command -v xdg-open >/dev/null 2>&1; then xdg-open "$url" elif command -v open >/dev/null 2>&1; then open "$url" fi } echo "" echo " AGV GLB 本地服务" echo "==================" echo "" PY=$(find_python) || { echo "错误: 未找到 Python 3.10+"; exit 1; } step "Python $($PY --version 2>&1 | awk '{print $2}') ($PY)" VENV_PY=$(venv_python || true) if [ "$SETUP" -eq 1 ]; then step "创建虚拟环境 .venv ..." if [ ! -x "$ROOT/.venv/bin/python" ]; then "$PY" -m venv .venv fi VENV_PY="$ROOT/.venv/bin/python" step "安装 Python 依赖 ..." "$VENV_PY" -m pip install --upgrade pip "$VENV_PY" -m pip install -r requirements.txt echo "依赖安装完成。" fi RUN_PY="${VENV_PY:-$PY}" if [ -n "$VENV_PY" ]; then step "使用虚拟环境: .venv" else step "使用系统 Python(serve.py 无需额外依赖)" echo "提示: 运行 ./start.sh --setup 可安装 analyze_agv.py 所需依赖" fi BASE="http://127.0.0.1:${PORT}" if port_in_use; then echo "警告: 端口 ${PORT} 已被占用。" echo " 播放页: ${BASE}/viewer/play.html" echo " 配置页: ${BASE}/viewer/index.html" [ "$NO_BROWSER" -eq 0 ] && open_browser exit 0 fi step "启动 serve.py (端口 ${PORT}) ..." export PORT "$RUN_PY" serve.py & SRV_PID=$! step "等待服务就绪 ..." if ! wait_ready; then echo "错误: 服务在 30 秒内未响应。" kill "$SRV_PID" 2>/dev/null || true exit 1 fi echo "" echo "服务已启动 (PID ${SRV_PID})" echo " 播放页: ${BASE}/viewer/play.html" echo " 配置页: ${BASE}/viewer/index.html" echo " API: GET ${BASE}/api/catalog | POST ${BASE}/api/agv" echo "" echo "关闭服务: kill ${SRV_PID} 或 Ctrl+C" echo "" [ "$NO_BROWSER" -eq 0 ] && open_browser wait "$SRV_PID"