From 76837d4ef047972b363b4ef74cd0aad0c5d75ad3 Mon Sep 17 00:00:00 2001 From: ThearchyHelios Date: Mon, 14 Sep 2026 14:20:20 +0800 Subject: [PATCH] =?UTF-8?q?dev.sh=EF=BC=9A=E7=AB=AF=E5=8F=A3=E8=A2=AB?= =?UTF-8?q?=E5=8D=A0=E6=97=B6=E6=8C=AA=E5=BC=80=EF=BC=8C=E5=B9=B6=E7=A1=AE?= =?UTF-8?q?=E8=AE=A4=E7=AD=94=E5=BA=94=E5=81=A5=E5=BA=B7=E6=A3=80=E6=9F=A5?= =?UTF-8?q?=E7=9A=84=E6=98=AF=E8=87=AA=E5=B7=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 踩到的坑:8000 被另一个项目长期占着(绑 *:8000),uvicorn 起不来直接退出, 而健康检查去探 8000 又被那个项目答应了,脚本以为后端就绪继续起前端—— 于是前端代理连着别人的服务,界面上全是陈年旧数据,还很难看出哪里不对。 三处收紧: - 端口被占就自动往后挪(显式指定 AGENTLAB_PORT 时则明确报错并列出占用方) - 健康检查要看到 service 是 agentlab 才算数,顺便看住后端进程别悄悄死了 - vite proxy 的目标端口跟着 AGENTLAB_PORT 走,不再硬编码 8000 --- frontend/vite.config.ts | 8 ++++++-- scripts/dev.sh | 31 +++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index e4349664..a1e5b139 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -2,14 +2,18 @@ import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' +// 后端端口跟着 dev.sh 走:8000 被别的项目占了它会自动挪,挪到哪就从 +// 环境变量告诉这边,否则前端会把请求代理到别人的服务上去。 +const API_PORT = process.env.AGENTLAB_PORT || '8000' + export default defineConfig({ plugins: [react(), tailwindcss()], server: { // 5173 太容易和别的项目撞车,挪开一点 port: 5273, proxy: { - // 后端跑在 8000,前端开发服务器代理过去,省掉跨域配置 - '/api': { target: 'http://127.0.0.1:8000', changeOrigin: true, ws: true }, + // 前端开发服务器代理到后端,省掉跨域配置 + '/api': { target: `http://127.0.0.1:${API_PORT}`, changeOrigin: true, ws: true }, }, }, }) diff --git a/scripts/dev.sh b/scripts/dev.sh index 861b1cac..b7ad9b48 100755 --- a/scripts/dev.sh +++ b/scripts/dev.sh @@ -22,6 +22,23 @@ PY_BIN="$(conda run -n "$CONDA_ENV" python -c 'import sys; print(sys.executable) echo "==> 后端解释器 $PY_BIN" [ -d "$ROOT/frontend/node_modules" ] || (cd "$ROOT/frontend" && pnpm install) +# 端口被别人占着就往后挪。踩过一次坑:8000 被另一个项目占住时,uvicorn +# 起不来直接退出,而下面的健康检查去探 8000 又被那个项目答应了,脚本以为 +# 后端就绪、继续起前端——于是前端连着别人的服务,界面显示的全是陈年旧数据。 +port_taken() { lsof -nP -iTCP:"$1" -sTCP:LISTEN >/dev/null 2>&1; } +if [ -z "${AGENTLAB_PORT:-}" ]; then + while port_taken "$API_PORT"; do + echo "==> 端口 $API_PORT 已被占用,换 $((API_PORT + 1))" + API_PORT=$((API_PORT + 1)) + done +elif port_taken "$API_PORT"; then + echo "端口 $API_PORT 已被占用(AGENTLAB_PORT 指定的),换一个或停掉占用方" + lsof -nP -iTCP:"$API_PORT" -sTCP:LISTEN | tail -n +2 | head -3 + exit 1 +fi +# 前端代理要跟着后端端口走,否则请求会打到占端口的那个服务上 +export AGENTLAB_PORT="$API_PORT" + cleanup() { echo echo "==> 停止" @@ -36,11 +53,21 @@ echo "==> 后端 http://127.0.0.1:$API_PORT" (cd "$ROOT/backend" && "$PY_BIN" -m uvicorn app.main:app --host 127.0.0.1 --port "$API_PORT" --reload) & API_PID=$! -# 等后端起来再起前端,省得前端第一次请求就打空 +# 等后端起来再起前端,省得前端第一次请求就打空。 +# 光看"有没有响应"不够——得确认答应的是 agentlab 自己,不是碰巧占着 +# 这个端口的别的服务;顺便看住后端进程别悄悄死了。 +ready="" for _ in $(seq 1 60); do - curl -sf "http://127.0.0.1:$API_PORT/api/health" >/dev/null 2>&1 && break + if ! kill -0 "$API_PID" 2>/dev/null; then + echo "后端启动失败,上面应该有它的报错" + exit 1 + fi + if curl -sf "http://127.0.0.1:$API_PORT/api/health" 2>/dev/null | grep -q '"agentlab"'; then + ready=1; break + fi sleep 0.5 done +[ -n "$ready" ] || { echo "后端 30s 内没就绪(或 $API_PORT 上答话的不是 agentlab)"; exit 1; } echo "==> 前端 http://localhost:$WEB_PORT" (cd "$ROOT/frontend" && pnpm dev --port "$WEB_PORT") &