| 8 | |
| 9 | |
| 10 | def run_cmd(cmd: str) -> Tuple[bool, str, str]: |
| 11 | # NOTE: 统一子进程调用,保留 stderr 以便上层进行错误提示与审计; |
| 12 | # 使用 shell 模式兼容内置 reg 命令,降低对外部依赖的耦合 |
| 13 | start = time.perf_counter() |
| 14 | try: |
| 15 | proc = run(cmd, shell=True, check=True, stdout=PIPE, stderr=PIPE, text=True) |
| 16 | return True, proc.stdout or "", proc.stderr or "" |
| 17 | except CalledProcessError as e: |
| 18 | duration_ms = int((time.perf_counter() - start) * 1000) |
| 19 | msg = e.stderr or e.stdout or str(e) |
| 20 | log_event( |
| 21 | logging.ERROR, |
| 22 | "subprocess_failed", |
| 23 | f"子进程执行失败: {msg}", |
| 24 | action="run_cmd", |
| 25 | status="failed", |
| 26 | cmd=cmd, |
| 27 | duration_ms=duration_ms, |
| 28 | error_type=type(e).__name__, |
| 29 | error_message=msg, |
| 30 | ) |
| 31 | return False, e.stdout or "", e.stderr or "" |
| 32 | except Exception as e: |
| 33 | duration_ms = int((time.perf_counter() - start) * 1000) |
| 34 | msg = str(e) |
| 35 | log_event( |
| 36 | logging.ERROR, |
| 37 | "subprocess_exception", |
| 38 | f"子进程异常: {msg}", |
| 39 | action="run_cmd", |
| 40 | status="failed", |
| 41 | cmd=cmd, |
| 42 | duration_ms=duration_ms, |
| 43 | error_type=type(e).__name__, |
| 44 | error_message=msg, |
| 45 | traceback=traceback.format_exc(), |
| 46 | exc_info=True, |
| 47 | ) |
| 48 | return False, "", msg |