From d8d646fcd52314cff32629fde1a3e08c2613df4b Mon Sep 17 00:00:00 2001 From: claude_dev Date: Sun, 16 Aug 2026 19:08:26 +0800 Subject: [PATCH] =?UTF-8?q?fix(#89+#90=E9=98=B2=E7=BA=BF):=20=E7=BB=84?= =?UTF-8?q?=E5=90=88=E5=9B=9E=E6=B5=8B=E9=80=89=E5=AE=9E=E4=BE=8B=E4=B8=8D?= =?UTF-8?q?=E5=86=8D=E9=A2=84=E5=A1=AB=E6=A0=87=E7=9A=84=E6=B1=A0+vps-depl?= =?UTF-8?q?oy=E5=83=B5=E5=B0=B8API=E7=AB=AF=E5=8F=A3=E5=AE=88=E5=8D=AB?= =?UTF-8?q?=E2=80=94=E2=80=94#89:prefillFromInstance=E5=88=A0symbol=5For?= =?UTF-8?q?=5Fpool=E2=86=92form.pool=E9=A2=84=E5=A1=AB(#86a=E5=AE=9A?= =?UTF-8?q?=E7=A8=BF=E5=AE=9E=E4=BE=8B=E4=B8=8D=E9=80=89=E6=A0=87=E7=9A=84?= =?UTF-8?q?,=E8=80=81=E5=AE=9E=E4=BE=8B=E5=AD=98=E7=9A=84all=E4=B8=8D?= =?UTF-8?q?=E8=AF=A5=E6=82=84=E6=82=84=E6=94=B9=E7=94=A8=E6=88=B7=E6=B1=A0?= =?UTF-8?q?=E9=80=89=E6=8B=A9;=E7=AD=96=E7=95=A5/max=5Fpool/benchmark?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E9=A2=84=E5=A1=AB=E4=BF=9D=E7=95=99);#90?= =?UTF-8?q?=E9=98=B2=E5=A4=8D=E5=8F=91:API=E9=87=8D=E5=90=AF=E6=AD=A5?= =?UTF-8?q?=E5=9C=A8/end=E5=90=8Enetstat=E6=9F=A58000=E6=8C=81=E6=9C=89PID?= =?UTF-8?q?=E5=BC=BA=E6=9D=80+=E7=AB=AF=E5=8F=A3=E6=9C=AA=E9=87=8A?= =?UTF-8?q?=E6=94=BE=E7=A1=ACfail(2026-08-16=E5=AE=9E=E5=BD=95uvicorn=20re?= =?UTF-8?q?load=E5=AD=A4=E5=84=BF=E5=AD=90=E8=BF=9B=E7=A8=8B17836=E8=B7=A8?= =?UTF-8?q?=E4=B8=A4=E8=BD=AE=E9=83=A8=E7=BD=B2=E5=8D=A0=E7=AB=AF=E5=8F=A3?= =?UTF-8?q?,=E6=96=B0=E5=AE=9E=E4=BE=8B=E9=9D=99=E9=BB=98=E6=8A=A2?= =?UTF-8?q?=E4=B8=8D=E5=88=B0,=E6=97=A7=E4=BB=A3=E7=A0=81=E7=BB=A7?= =?UTF-8?q?=E7=BB=ADserve=E2=86=92500=E6=97=A7bug=E9=87=8D=E7=8E=B0,?= =?UTF-8?q?=E4=BA=BA=E5=B7=A5taskkill+=E9=87=8D=E6=8B=89=E5=90=8E=E5=90=8C?= =?UTF-8?q?=E8=AF=B7=E6=B1=82200+task=5Fid=E5=AE=9E=E8=AF=81);build?= =?UTF-8?q?=E7=BB=BF+yaml=E8=A7=A3=E6=9E=90=E8=BF=87=20[nas]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitea/workflows/vps-deploy.yml | 13 +++++++++++-- frontend/src/views/backtest/PortfolioBacktest.vue | 3 ++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.gitea/workflows/vps-deploy.yml b/.gitea/workflows/vps-deploy.yml index 1784a24..bfdb734 100644 --- a/.gitea/workflows/vps-deploy.yml +++ b/.gitea/workflows/vps-deploy.yml @@ -66,12 +66,21 @@ jobs: set -e ssh 49.232.102.198 'C:\Python310\python.exe -X utf8 C:\sanguo_vnpy_v2\scripts\nas_sync\vps_update_dist.py' | tee /tmp/dist_swap.log grep -q DIST_UPDATE_DONE /tmp/dist_swap.log - # 停 API → 等端口彻底释放(旧实例被杀后端口有滞留, 立即重启会 10048 静默崩) + # 停 API → 僵尸端口守卫 → 等端口彻底释放(否则 fail) → 重启 + # 2026-08-16 实录: /end 杀不掉 uvicorn reload 孤儿子进程, 旧进程跨两轮 + # 部署占 8000, 新实例静默抢不到端口, /docs 200 验的还是旧代码 → 500 旧 bug 重现 ssh 49.232.102.198 'schtasks /end /tn sanguo-api' || true + ZPID=$(ssh 49.232.102.198 'netstat -ano -p tcp' | tr -d '\r' | grep ':8000' | grep -i LISTENING | awk '{print $NF}' | sort -u | head -1) + if [ -n "$ZPID" ]; then + echo "僵尸 API 进程 PID=$ZPID 仍占 8000, 强杀" + ssh 49.232.102.198 "taskkill /F /T /PID $ZPID" || true + fi + PORT_FREED=0 for i in $(seq 1 30); do - ssh 49.232.102.198 'netstat -ano -p tcp' | tr -d '\r' | grep -q ':8000.*LISTEN' || { echo "port freed after $((i*2))s"; break; } + ssh 49.232.102.198 'netstat -ano -p tcp' | tr -d '\r' | grep -q ':8000.*LISTEN' || { echo "port freed after $((i*2))s"; PORT_FREED=1; break; } sleep 2 done + if [ "$PORT_FREED" != "1" ]; then echo "❌ 端口 8000 未释放, 强杀后重启会 10048, 终止"; exit 1; fi ssh 49.232.102.198 'schtasks /run /tn sanguo-api' # 等新实例监听 + /docs 可用(VPS 启动需数分钟, 上限 10 分钟) for i in $(seq 1 60); do diff --git a/frontend/src/views/backtest/PortfolioBacktest.vue b/frontend/src/views/backtest/PortfolioBacktest.vue index 4c5d6c2..afa5d8a 100644 --- a/frontend/src/views/backtest/PortfolioBacktest.vue +++ b/frontend/src/views/backtest/PortfolioBacktest.vue @@ -436,7 +436,8 @@ async function prefillFromInstance(instId: number): Promise { const p = inst.params || {} if (typeof p.max_pool === 'number') form.max_pool = p.max_pool if (typeof p.benchmark === 'string') form.benchmark = p.benchmark - if (inst.symbol_or_pool && inst.symbol_or_pool !== '') form.pool = inst.symbol_or_pool + // #89 标的池不预填:#86a 定稿「实例不选标的,发起时定」——老实例存的 + // symbol_or_pool(all 等)不该悄悄改用户的池选择 } catch { /* 预填失败走默认 */ }