#!/usr/bin/env python3 """ retry_wrapper.py — 可配置的重试包装器 配置文件: ~/.hermes/config/retry_jobs.json 配置格式: { "jobs": { "job_name": { "script": "original_script.py", "max_retries": 3, "delay": 5 } } } """ import subprocess import sys import time import os import json from pathlib import Path CONFIG_FILE = Path.home() / ".hermes" / "config" / "retry_jobs.json" def load_config(): """加载重试配置""" if not CONFIG_FILE.exists(): return {} try: with open(CONFIG_FILE, 'r', encoding='utf-8') as f: return json.load(f) except Exception as e: print(f"警告: 无法加载配置: {e}") return {} def get_job_config(job_name): """获取指定job的配置""" config = load_config() jobs = config.get('jobs', {}) return jobs.get(job_name, None) def run_script(script_path, max_retries=3, delay=5): """执行脚本,带重试""" # 检查脚本是否存在 if not os.path.exists(script_path): # 尝试在scripts目录查找 scripts_dir = os.path.expanduser("~/.hermes/scripts") script_path = os.path.join(scripts_dir, script_path) if not os.path.exists(script_path): print(f"错误: 脚本不存在: {script_path}") return 1 # 确定执行方式 if script_path.endswith('.py'): cmd = [sys.executable, script_path] elif script_path.endswith('.sh'): cmd = ['bash', script_path] else: cmd = [script_path] last_output = "" last_exit_code = 1 for attempt in range(1, max_retries + 1): print(f"尝试 {attempt}/{max_retries}: {os.path.basename(script_path)}") try: result = subprocess.run( cmd, capture_output=True, text=True, timeout=300 # 5分钟超时 ) last_output = result.stdout + result.stderr last_exit_code = result.returncode if result.returncode == 0: print(last_output) return 0 print(f"失败 (退出码: {result.returncode})") if result.stderr: print(f"错误: {result.stderr[:200]}") except subprocess.TimeoutExpired: print(f"超时 (5分钟)") last_exit_code = 124 except Exception as e: print(f"异常: {e}") last_exit_code = 1 if attempt < max_retries: print(f"等待 {delay}s 后重试...") time.sleep(delay) print(f"\n所有 {max_retries} 次重试失败") if last_output: print(f"最后输出:\n{last_output[:500]}") return last_exit_code def main(): # 从文件名推断job名 script_name = Path(__file__).stem job_name = script_name.replace("retry_", "") # 获取配置 job_config = get_job_config(job_name) if job_config: script = job_config.get('script') max_retries = job_config.get('max_retries', 3) delay = job_config.get('delay', 5) else: # 默认配置 print(f"警告: 未找到job '{job_name}' 的配置,使用默认值") script = job_name + ".py" max_retries = 3 delay = 5 return run_script(script, max_retries, delay) if __name__ == "__main__": sys.exit(main())