xiaowei-system/scripts/retry_wrapper.py

127 lines
3.4 KiB
Python

#!/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())