From 8d8bc409a61708072054b6f718fd153b5fc78ed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=87=E8=96=87=E5=AE=89?= Date: Wed, 21 Jan 2026 17:11:13 +0800 Subject: [PATCH] a --- backend/api/routes/accounts.py | 31 +++++++++++++++++++++++++++++-- backend/api/supervisor_account.py | 16 ++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/backend/api/routes/accounts.py b/backend/api/routes/accounts.py index cdb4b26..f85bc2c 100644 --- a/backend/api/routes/accounts.py +++ b/backend/api/routes/accounts.py @@ -19,6 +19,7 @@ from api.supervisor_account import ( run_supervisorctl, parse_supervisor_status, program_name_for_account, + tail_supervisor, ) 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) return {"message": "已启动", "output": out, "status": {"program": program, "running": running, "pid": pid, "state": state, "raw": raw}} 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") @@ -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) return {"message": "已重启", "output": out, "status": {"program": program, "running": running, "pid": pid, "state": state, "raw": raw}} 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, + }, + ) diff --git a/backend/api/supervisor_account.py b/backend/api/supervisor_account.py index 1ea3993..1b23641 100644 --- a/backend/api/supervisor_account.py +++ b/backend/api/supervisor_account.py @@ -256,6 +256,22 @@ def parse_supervisor_status(raw: str) -> Tuple[bool, Optional[int], str]: return False, None, "UNKNOWN" +def tail_supervisor(program: str, stream: str = "stderr", lines: int = 120) -> str: + """ + 读取 supervisor 进程最近日志(stdout/stderr)。 + supervisorctl tail - [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 class EnsureProgramResult: ok: bool