127 lines
3.4 KiB
Python
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())
|