🤖 Hermes Cron 治理手册
版本: 1.0 | 更新日期: 2026-05-15 | 维护人: Hermes Agent
📑 目录
1. 🏗️ 架构概览
Hermes Cron 采用 Master Orchestrator 模式,所有定时任务由单一编排脚本统一调度:
- 执行时间: 每天凌晨
01:00(Asia/Shanghai) - 执行模式: 串行(按序执行),支持依赖链检查
- 超时控制: 每个任务独立配置超时时间,超时自动 SIGTERM
- 报告机制: 不单独发任务结果,统一生成日报 Markdown 文件
- 传递模式:
no_agent=true,脚本直出,零 Token 开销
┌─────────────────────────────────────────┐
│ hermes-cron-master │
│ cronjob (01:00 daily) │
│ no_agent=true │
└────────────────┬────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ /www/kc-ai-hermes/cron/run.sh │
│ Master Orchestrator (bash) │
└────┬──────────────┬─────────────────────┘
│ │
▼ ▼
┌──────────┐ ┌──────────────┐
│ gbrain │ │ sitemap │
│ daily │ │ auto-update │
│ dream │ │ │
└──────────┘ └──────────────┘
│ │
▼ ▼
┌─────────────────────────────────────────┐
│ lib/report.sh │
│ 日报生成引擎 │
└────────────────┬────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ runreport/cron-YYYY-MM-DD.md │
│ 📊 统一日报文件(Markdown) │
└─────────────────────────────────────────┘
2. 📂 目录结构
/www/kc-ai-hermes/
└── cron/
├── tasks.conf # 【配置】任务定义(顺序/超时/依赖)
├── run.sh # 【核心】主编排脚本
├── lib/
│ └── report.sh # 【库】日报生成引擎
├── gbrain-daily-dream/
│ └── run.sh # 【任务1】gbrain 全量维护
├── sitemap-auto-update/
│ └── run.sh # 【任务2】Trilium sitemap 更新
├── <新任务名称>/ # 【约定】每个任务独占一个子目录
│ └── run.sh
└── runreport/
└── cron-2026-05-15.md # 【产出】日审文件(自动生成)
说明:
- 所有 cron 脚本的统一根目录为
/www/kc-ai-hermes/cron/ - 每个任务独立一个子目录,入口脚本统一命名为
run.sh - 日报文件自动生成,无需手动创建
3. ⚙️ 任务定义
所有任务在 tasks.conf 中声明,采用 bash 关联数组格式:
# ===== tasks.conf =====
declare -A TASK_ORDER # 执行顺序(数字越小越先执行)
declare -A TASK_TIMEOUT # 超时时间(秒)
declare -A TASK_DEPENDS # 依赖关系(逗号分隔,空=无依赖)
# 任务1: gbrain 每日维护
TASK_ORDER[gbrain-daily-dream]=1
TASK_TIMEOUT[gbrain-daily-dream]=600
TASK_DEPENDS[gbrain-daily-dream]=""
# 任务2: Trilium sitemap 自动更新
TASK_ORDER[sitemap-auto-update]=2
TASK_TIMEOUT[sitemap-auto-update]=120
TASK_DEPENDS[sitemap-auto-update]=""
当前任务清单
| 序号 | 任务名称 | 超时 | 依赖 | 说明 |
|---|---|---|---|---|
| 1 | gbrain-daily-dream | 600s (10min) | — | gbrain dream --pull --json + stats |
| 2 | sitemap-auto-update | 120s (2min) | — | 爬取 Trilium 共享页面,更新 sitemap.xml |
4. ➕ 新增任务
步骤一:创建任务目录和脚本
mkdir -p /www/kc-ai-hermes/cron/your-task-name
touch /www/kc-ai-hermes/cron/your-task-name/run.sh
chmod +x /www/kc-ai-hermes/cron/your-task-name/run.sh
步骤二:编写 run.sh
任务脚本只需关注自己的业务逻辑,stdout 会被编排器捕获写入日报。
#!/usr/bin/env bash
# run.sh - 你的任务
set -o pipefail
echo "🚀 你的任务开始..."
# 你的业务逻辑
echo "✅ 你的任务完成"
步骤三:注册到 tasks.conf
# 在 tasks.conf 末尾追加
TASK_ORDER[your-task-name]=3 # 新序号
TASK_TIMEOUT[your-task-name]=300 # 超时秒数
TASK_DEPENDS[your-task-name]="" # 可选依赖
步骤四:验证
# 语法检查
bash -n /www/kc-ai-hermes/cron/run.sh
bash -n /www/kc-ai-hermes/cron/your-task-name/run.sh
# 单任务测试(不会影响正式 cron)
cd /www/kc-ai-hermes/cron && bash run.sh --task=your-task-name
5. ❌ 移除任务
# 1. 从 tasks.conf 中删除对应三行
# 2. (可选)删除任务目录
rm -rf /www/kc-ai-hermes/cron/your-task-name
# 3. 验证
bash -n /www/kc-ai-hermes/cron/tasks.conf
cd /www/kc-ai-hermes/cron && bash run.sh --test
6. 🔗 依赖关系
支持任务间依赖链,当依赖任务失败时,下游任务自动跳过并在日报中标注。
# 示例:任务3 依赖 任务1 和 任务2
TASK_ORDER[task-c]=3
TASK_TIMEOUT[task-c]=300
TASK_DEPENDS[task-c]="gbrain-daily-dream,sitemap-auto-update"
# 示例:任务4 仅依赖 任务1
TASK_ORDER[task-d]=4
TASK_TIMEOUT[task-d]=120
TASK_DEPENDS[task-d]="gbrain-daily-dream"
行为规则:
- 依赖任务失败 → 跳过当前任务(状态标记为 ⏭️ 跳过)
- 日报中清楚标注跳过原因和缺失的依赖
- 依赖可以为空字符串(无依赖)
- 依赖链层级不限,但建议不超过 3 层
7. ⏰ 超时机制
每个任务独立配置超时,编排器使用 Linux timeout 命令强制终止:
- 超时行为: 发送 SIGTERM(15)信号,超时后立即 kill 任务进程
- 超时退出码: 124(timeout 命令标准约定)
- 超时后果: 任务标记为 ❌ 失败(超时),不影响后续任务执行
- 建议值: 常规任务 120-300s,耗时任务 300-600s
注:timeout 不区分 SIGTERM 和 SIGKILL — 超时即视为失败,不会自动重试。
8. 📊 日报机制
输出流程
- 逐个运行任务,捕获 stdout / stderr(各截取前 2000 字符)/ 退出码 / 耗时
- 生成日报 Markdown,包含总体概览 + 每个任务的详细执行记录
- 保存到磁盘:
/www/kc-ai-hermes/cron/runreport/cron-YYYY-MM-DD.md - 发送摘要 到 Telegram(仅总体统计 + 任务状态一览,不含完整输出)
日报文件示例
# 🤖 Hermes Cron 日报 — 2026-05-15
## 📊 总体概览
- 任务总数: 2
- ✅ 成功: 1
- ❌ 失败: 0
- ⏭️ 跳过: 1
- ⏱️ 总耗时: 3s
### [1] gbrain-daily-dream — ✅ 成功
- 退出码: 0
- 耗时: 6s
**标准输出:**
```
🤖 gbrain Daily Dream
--- Step 1: gbrain dream --pull --json ---
...
```
### [2] sitemap-auto-update — ⏭️ 跳过
- 退出码: N/A
- 耗时: N/A
**标准错误:**
依赖 'gbrain-daily-dream' 未成功
---
*报告生成时间: 2026-05-15*
日报保留策略
日报文件按日期命名,永久保留。建议定期归档或清理超过 90 天的旧文件:
# 查看日报目录大小
du -sh /www/kc-ai-hermes/cron/runreport/
# 清理 90 天前的日报(可选)
find /www/kc-ai-hermes/cron/runreport/ -name 'cron-*.md' -mtime +90 -delete
9. 🔧 运维指南
查看当前任务
通过 Telegram 询问 Hermes:
[at c] 列出目前所有cron
或直接使用 cron job 列表:
# 查看 cron job 状态(在 Hermes 内执行)
hermes cron list
# 或通过 cronjob tool
手动触发运行
# 全量运行
cd /www/kc-ai-hermes/cron && bash run.sh
# 运行单个任务
cd /www/kc-ai-hermes/cron && bash run.sh --task=sitemap-auto-update
查看历史日报
ls -la /www/kc-ai-hermes/cron/runreport/
cat /www/kc-ai-hermes/cron/runreport/cron-2026-05-15.md
修改执行时间
通过 Hermes 修改 cron job 的 schedule 参数:
[at c] 把 cron 改为每天凌晨 2 点
暂停/恢复
通过 Hermes 暂停整个 cron 管线:
[at c] 暂停所有cron
[at c] 恢复cron
紧急停止正在运行的任务
如果某个任务卡死,通过 Hermes 操作:
# 编排器运行中时,直接 kill 进程
pkill -f "run.sh" # 谨慎使用,会终止所有 cron 任务
10. ❓ FAQ
Q: 为什么用 no_agent=true?
因为 run.sh 脚本本身已经是完整的编排引擎 — 它按序执行任务、捕获输出、生成日报。不需要 LLM 介入,免 Token 消耗。
Q: 日报文件太大怎么办?
每个任务的 stdout/stderr 只截取前 2000 字符,文件通常不超过 50KB。如仍嫌大,可在 run.sh 中调整 head -c 2000 的值。
Q: 任务脚本如何引用环境变量?
任务脚本在 cron 环境中运行,可直接使用 Hermes 的环境变量(如 $TRILIUM_ETAPI_TOKEN)。如需额外变量,在 run.sh 中加载即可。
Q: 串行执行的话,任务多了会不会时间不够?
目前 2 个任务总耗时约 10s。即便增加到 10-20 个任务,通常也能在 1 小时内完成。凌晨 1 点到早上 7 点有 6 小时的窗口期,非常充裕。
Q: 如何临时跳过某个任务而不删除它?
在 tasks.conf 中注释掉对应行,或在任务 run.sh 开头加 exit 0 快速跳过。
— 本文档由 Hermes Agent 自动生成并维护于 Trilium