Hermes Cron 治理手册 📋

🤖 Hermes Cron 治理手册

版本: 1.0 | 更新日期: 2026-05-15 | 维护人: Hermes Agent


📑 目录

  1. 架构概览
  2. 目录结构
  3. 任务定义
  4. 新增任务
  5. 移除任务
  6. 依赖关系
  7. 超时机制
  8. 日报机制
  9. 运维指南
  10. FAQ

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. 📊 日报机制

输出流程

  1. 逐个运行任务,捕获 stdout / stderr(各截取前 2000 字符)/ 退出码 / 耗时
  2. 生成日报 Markdown,包含总体概览 + 每个任务的详细执行记录
  3. 保存到磁盘: /www/kc-ai-hermes/cron/runreport/cron-YYYY-MM-DD.md
  4. 发送摘要 到 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