2.6 KiB
2.6 KiB
Cron Wrapper 脚本诊断与修复(2026-07-17 实测)
症状
Script not found: /home/muc/.hermes/scripts/skill-manager.py scan
Script not found: /home/muc/.hermes/scripts/optimizer.py report
明明文件存在,但 cron 报找不到。
根因
hermes cron 的 no_agent 模式把 script 字段当作完整文件名处理——带空格的字符串不会被解析为"脚本名 + 参数",而是当作单个带空格的文件名。
# cron 定义的 script 字段:
script: "skill-manager.py scan" # ❌ 找 "skill-manager.py scan" 这个文件(不存在)
script: "skill-manager.py" # ❌ 如果 scan 是参数,也找不到
诊断脚本
# 检查所有 no_agent cron 的 script 字段是否包含空格
hermes cron list 2>/dev/null | grep -B2 "no-agent" | grep "Script:"
# 或者直接查 wrapper 脚本内容
for f in ~/.hermes/scripts/*.sh; do
content=$(cat "$f" 2>/dev/null)
# 找有问题的模式:python3 xxx.py 后面直接跟命令,中间没有换行
if echo "$content" | grep -qE "python3.*\.py [a-z]"; then
echo "❌ $f 有问题(缺换行)"
fi
done
正确写法
#!/bin/bash
python3 ~/.hermes/scripts/skill-manager.py scan
# ↑ 换行,不是空格
#!/bin/bash
cd ~/.hermes/scripts && python3 optimizer.py report
# ↑ 换行
批量检测
# 查 cron job 配置中的问题 script
import json
with open(os.path.expanduser("~/.hermes/cron/jobs.json")) as f:
jobs = json.load(f)
issues = []
for job in jobs.get("jobs", []):
script = job.get("script", "")
mode = job.get("no_agent", False)
if mode and " " in script and not script.endswith(".sh"):
issues.append(f" ❌ {job['name']} ({job['id']}): script='{script}'")
if issues:
print("检测到 cron wrapper 问题:")
for i in issues: print(i)
else:
print("✅ 无 cron wrapper 问题")
今天修复的受影响 cron(4个)
| Cron ID | 名称 | 原因 |
|---|---|---|
| c143d2afe640 | 技能健康扫描 | skill-manager-scan.sh 缺换行符 |
| 1e19f7429ddf | 自我优化报告 | optimizer-report.sh 同上 |
| b192a7cec1b5 | 主动学习自检报告 | proactive-learning-report.sh 同上 |
| 6061a782b772 | 股票投研周学习 | stock_learning.sh 不存在 |
预防
新增任何 cron job 时,如果 script 是 Python/脚本带参数:
- 先写
xxx.shwrapper(#!/bin/bash+ 单行python3 ...) - 再用 wrapper 路径作为 script 字段值
- 用上面的诊断脚本验证
hermes cron 的 no_agent 模式不支持参数展开,任何参数都必须 bake 进 wrapper 脚本里。