109 lines
3.6 KiB
Bash
Executable File
109 lines
3.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
set -eo pipefail
|
||
|
||
ROOT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||
cd "$ROOT_DIR"
|
||
|
||
PYTHON="$ROOT_DIR/.venv/bin/python"
|
||
FRONTEND_DIR="$ROOT_DIR/web/frontend"
|
||
BACKEND_PORT=8000
|
||
FRONTEND_PORT=5173
|
||
HEALTH_TIMEOUT=30 # 后端健康检查最长等待秒数
|
||
|
||
# ── 工具函数 ──────────────────────────────────────────────
|
||
|
||
log() { echo "[$(date '+%H:%M:%S')] $*"; }
|
||
warn() { echo "[$(date '+%H:%M:%S')] ⚠️ $*" >&2; }
|
||
die() { echo "[$(date '+%H:%M:%S')] ❌ $*" >&2; exit 1; }
|
||
|
||
check_port() {
|
||
if lsof -iTCP:"$1" -sTCP:LISTEN -P &>/dev/null; then
|
||
die "端口 $1 已被占用,请先释放或更改端口号(lsof -i :$1)"
|
||
fi
|
||
}
|
||
|
||
# ── 预检查 ────────────────────────────────────────────────
|
||
|
||
check_port "$BACKEND_PORT"
|
||
check_port "$FRONTEND_PORT"
|
||
|
||
if [ ! -f "$PYTHON" ]; then
|
||
log "未找到 .venv,正在创建..."
|
||
uv venv .venv
|
||
uv pip install -e .
|
||
fi
|
||
|
||
if [ ! -d "$FRONTEND_DIR/node_modules" ]; then
|
||
log "前端依赖未安装,正在安装..."
|
||
(cd "$FRONTEND_DIR" && npm install)
|
||
fi
|
||
|
||
# ── 启动信息 ──────────────────────────────────────────────
|
||
|
||
echo ""
|
||
echo "=============================="
|
||
echo " 斗鱼批量登录 - Web 后台"
|
||
echo "=============================="
|
||
echo " 后端: http://localhost:$BACKEND_PORT"
|
||
echo " 前端: http://localhost:$FRONTEND_PORT"
|
||
echo " 默认账号见环境变量 ADMIN_USERNAME/ADMIN_PASSWORD(未设置则为 admin/admin123)"
|
||
echo " 按 Ctrl+C 停止所有服务"
|
||
echo "=============================="
|
||
echo ""
|
||
|
||
# ── 清理子进程 ────────────────────────────────────────────
|
||
|
||
PIDS=()
|
||
|
||
cleanup() {
|
||
echo ""
|
||
log "正在停止服务..."
|
||
for pid in "${PIDS[@]}"; do
|
||
if kill -0 "$pid" 2>/dev/null; then
|
||
kill "$pid" 2>/dev/null
|
||
fi
|
||
done
|
||
for pid in "${PIDS[@]}"; do
|
||
wait "$pid" 2>/dev/null
|
||
done
|
||
log "已停止"
|
||
}
|
||
trap cleanup EXIT INT TERM
|
||
|
||
# ── 启动后端 ──────────────────────────────────────────────
|
||
|
||
log "启动后端 (FastAPI :$BACKEND_PORT)..."
|
||
RELOAD_FLAG=""
|
||
if [ "${UVICORN_RELOAD:-true}" = "true" ]; then
|
||
RELOAD_FLAG="--reload"
|
||
fi
|
||
"$PYTHON" -m uvicorn web.backend.main:app --host 0.0.0.0 --port "$BACKEND_PORT" $RELOAD_FLAG &
|
||
PIDS+=($!)
|
||
|
||
# 等后端就绪(健康检查循环替代固定 sleep)
|
||
log "等待后端就绪(最多 ${HEALTH_TIMEOUT}s)..."
|
||
elapsed=0
|
||
while [ "$elapsed" -lt "$HEALTH_TIMEOUT" ]; do
|
||
if curl -sf "http://localhost:$BACKEND_PORT/docs" -o /dev/null 2>/dev/null; then
|
||
log "后端已就绪 ✓"
|
||
break
|
||
fi
|
||
sleep 1
|
||
elapsed=$((elapsed + 1))
|
||
done
|
||
if [ "$elapsed" -ge "$HEALTH_TIMEOUT" ]; then
|
||
warn "后端未在 ${HEALTH_TIMEOUT}s 内就绪,前端可能无法正常连接"
|
||
fi
|
||
|
||
# ── 启动前端 ──────────────────────────────────────────────
|
||
|
||
log "启动前端 (Vite :$FRONTEND_PORT)..."
|
||
cd "$FRONTEND_DIR"
|
||
npm run dev -- --port "$FRONTEND_PORT" --host 0.0.0.0 &
|
||
PIDS+=($!)
|
||
cd "$ROOT_DIR"
|
||
|
||
# ── 等待子进程 ────────────────────────────────────────────
|
||
|
||
wait
|