This commit is contained in:
薇薇安 2026-01-21 17:11:13 +08:00
parent d7813bbc80
commit 8d8bc409a6
2 changed files with 45 additions and 2 deletions

View File

@ -19,6 +19,7 @@ from api.supervisor_account import (
run_supervisorctl, run_supervisorctl,
parse_supervisor_status, parse_supervisor_status,
program_name_for_account, program_name_for_account,
tail_supervisor,
) )
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -227,7 +228,20 @@ async def trading_start_for_account(account_id: int, user: Dict[str, Any] = Depe
running, pid, state = parse_supervisor_status(raw) running, pid, state = parse_supervisor_status(raw)
return {"message": "已启动", "output": out, "status": {"program": program, "running": running, "pid": pid, "state": state, "raw": raw}} return {"message": "已启动", "output": out, "status": {"program": program, "running": running, "pid": pid, "state": state, "raw": raw}}
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=f"启动交易进程失败: {e}") tail = ""
try:
tail = tail_supervisor(program, "stderr", 120)
except Exception:
tail = ""
raise HTTPException(
status_code=500,
detail={
"error": f"启动交易进程失败: {e}",
"program": program,
"hint": "如果是 spawn error重点看 stderr_tail常见python 路径不可执行/依赖缺失/权限/工作目录不存在)",
"stderr_tail": tail,
},
)
@router.post("/{account_id}/trading/stop") @router.post("/{account_id}/trading/stop")
@ -253,5 +267,18 @@ async def trading_restart_for_account(account_id: int, user: Dict[str, Any] = De
running, pid, state = parse_supervisor_status(raw) running, pid, state = parse_supervisor_status(raw)
return {"message": "已重启", "output": out, "status": {"program": program, "running": running, "pid": pid, "state": state, "raw": raw}} return {"message": "已重启", "output": out, "status": {"program": program, "running": running, "pid": pid, "state": state, "raw": raw}}
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=f"重启交易进程失败: {e}") tail = ""
try:
tail = tail_supervisor(program, "stderr", 120)
except Exception:
tail = ""
raise HTTPException(
status_code=500,
detail={
"error": f"重启交易进程失败: {e}",
"program": program,
"hint": "如果是 spawn error重点看 stderr_tail常见python 路径不可执行/依赖缺失/权限/工作目录不存在)",
"stderr_tail": tail,
},
)

View File

@ -256,6 +256,22 @@ def parse_supervisor_status(raw: str) -> Tuple[bool, Optional[int], str]:
return False, None, "UNKNOWN" return False, None, "UNKNOWN"
def tail_supervisor(program: str, stream: str = "stderr", lines: int = 120) -> str:
"""
读取 supervisor 进程最近日志stdout/stderr
supervisorctl tail -<n> <program> [stdout|stderr]
"""
s = (stream or "stderr").strip().lower()
if s not in {"stdout", "stderr"}:
s = "stderr"
n = int(lines or 120)
if n < 20:
n = 20
if n > 500:
n = 500
return run_supervisorctl(["tail", f"-{n}", str(program), s])
@dataclass @dataclass
class EnsureProgramResult: class EnsureProgramResult:
ok: bool ok: bool