141 lines
3.3 KiB
Bash
141 lines
3.3 KiB
Bash
#!/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"
|