Files
sanguo_vnpy_v2/scripts/ci/vps_count_engines.py
T

47 lines
1.8 KiB
Python

"""VPS 引擎数清点(vps_restart_resident.sh 核验用,2026-08-30 live_17/20 教训)。
用法(promote 已部署到 VPS C:\\sanguo_vnpy_v2\\scripts\\ci\\ 后,经 ssh 调):
python vps_count_engines.py expected # 杀树前:DB running 数(期望值)
python vps_count_engines.py actual # 重拉后:实际引擎进程数
输出一行 ``LIVE=<n> SHADOW=<m>``。两种模式必须分开调——expected 必须在杀树
之前取,重拉后 DB 的 status 已被死亡事件改写,再查就不是期望了。
自匹配陷阱:本进程(wmic 的父 python)命令行只含本脚本路径,不含
``sanguo_portfolio.runner_live`` / ``sanguo_trader.shadow --account`` 字样,
wmic.exe 又被 name='python.exe' 过滤——计数不会把自己算进去(08-30 手工
wmic 探测时 -c 脚本文本含关键字曾 +1 误计)。
"""
import sqlite3
import subprocess
import sys
DB = r"C:\sanguo_vnpy_v2\data\backtest_results.db"
def _expected() -> tuple[int, int]:
c = sqlite3.connect(DB)
live = c.execute(
"select count(*) from live_accounts where status='running'").fetchone()[0]
shadow = c.execute(
"select count(*) from paper_accounts where status='running'").fetchone()[0]
c.close()
return live, shadow
def _actual() -> tuple[int, int]:
out = subprocess.run(
["wmic", "process", "where", "name='python.exe'",
"get", "CommandLine", "/format:csv"],
capture_output=True, text=True, errors="replace").stdout
lines = out.splitlines()
live = sum("sanguo_portfolio.runner_live" in l for l in lines)
shadow = sum("sanguo_trader.shadow --account" in l for l in lines)
return live, shadow
if __name__ == "__main__":
mode = sys.argv[1] if len(sys.argv) > 1 else ""
live, shadow = _expected() if mode == "expected" else _actual()
print(f"LIVE={live} SHADOW={shadow}")