a
This commit is contained in:
parent
fc128f98b4
commit
3154dd5518
|
|
@ -277,7 +277,8 @@ def parse_supervisor_status(raw: str) -> Tuple[bool, Optional[int], str]:
|
|||
def tail_supervisor(program: str, stream: str = "stderr", lines: int = 120) -> str:
|
||||
"""
|
||||
读取 supervisor 进程最近日志(stdout/stderr)。
|
||||
supervisorctl tail -<n> <program> [stdout|stderr]
|
||||
⚠️ 修复:优先直接读取日志文件,避免 XML-RPC 编码错误。
|
||||
如果 supervisorctl tail 失败(编码错误),回退到直接读取文件。
|
||||
"""
|
||||
s = (stream or "stderr").strip().lower()
|
||||
if s not in {"stdout", "stderr"}:
|
||||
|
|
@ -287,13 +288,38 @@ def tail_supervisor(program: str, stream: str = "stderr", lines: int = 120) -> s
|
|||
n = 20
|
||||
if n > 500:
|
||||
n = 500
|
||||
|
||||
# 优先尝试通过 supervisorctl tail(正常情况)
|
||||
try:
|
||||
return run_supervisorctl(["tail", f"-{n}", str(program), s])
|
||||
except Exception as e:
|
||||
# 如果 supervisorctl tail 失败(可能是编码错误),尝试直接读取日志文件
|
||||
error_msg = str(e)
|
||||
if "UnicodeDecodeError" in error_msg or "utf-8" in error_msg.lower() or "codec" in error_msg.lower():
|
||||
# 尝试从程序名解析 account_id(例如 auto_sys_acc4 -> 4)
|
||||
try:
|
||||
m = re.match(r"^auto_sys_acc(\d+)$", program)
|
||||
if m:
|
||||
account_id = int(m.group(1))
|
||||
project_root = _get_project_root()
|
||||
log_dir, out_log, err_log = expected_trading_log_paths(project_root, account_id)
|
||||
# 根据 stream 选择对应的日志文件
|
||||
log_file = out_log if s == "stdout" else err_log
|
||||
if log_file.exists():
|
||||
# 直接读取文件,使用宽松的编码处理
|
||||
return _tail_text_file(log_file, lines=n)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 如果所有尝试都失败,返回错误信息(但不要抛出异常,避免影响主流程)
|
||||
return f"[读取日志失败: {error_msg}]"
|
||||
|
||||
|
||||
def _tail_text_file(path: Path, lines: int = 200, max_bytes: int = 64 * 1024) -> str:
|
||||
"""
|
||||
读取文本文件末尾(用于 supervisor spawn error 等场景,program stderr 可能为空)。
|
||||
尽量只读最后 max_bytes,避免大文件占用内存。
|
||||
⚠️ 修复:使用更宽松的编码处理,支持中文等多字节字符。
|
||||
"""
|
||||
try:
|
||||
p = Path(path)
|
||||
|
|
@ -305,7 +331,21 @@ def _tail_text_file(path: Path, lines: int = 200, max_bytes: int = 64 * 1024) ->
|
|||
if size > read_size:
|
||||
f.seek(-read_size, os.SEEK_END)
|
||||
data = f.read()
|
||||
|
||||
# ⚠️ 修复:尝试多种编码,优先 UTF-8,失败则尝试常见中文编码
|
||||
text = None
|
||||
encodings = ["utf-8", "gbk", "gb2312", "gb18030", "latin1"]
|
||||
for enc in encodings:
|
||||
try:
|
||||
text = data.decode(enc, errors="strict")
|
||||
break
|
||||
except (UnicodeDecodeError, LookupError):
|
||||
continue
|
||||
|
||||
# 如果所有编码都失败,使用 errors="ignore" 强制解码(会丢失部分字符但不会报错)
|
||||
if text is None:
|
||||
text = data.decode("utf-8", errors="ignore")
|
||||
|
||||
# 仅保留最后 N 行
|
||||
parts = text.splitlines()
|
||||
if not parts:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user