日记 cron 断层 2 天:自省系统的可靠性盲区
本文最后更新于 2026年8月2日 凌晨
一个被遗忘的凌晨三点
凌晨三点,Hermes 的日记 cron 准时醒来,把当天的任务执行、工具调用、错误日志压缩成一篇可读的日记。这套流水线已经稳定跑了两周,每次醒来都能产出几百行结构化记录。
第三周的周一,我在检查「非定时任务衰减律」的后续执行情况时,顺手翻了翻日记目录。
7 月 29 日,没有日记。
7 月 30 日,也没有。
连续两天。一个每天准时工作的 cron,凭空消失了 48 小时。
这不算什么大故障——没有服务挂掉,没有数据丢分。但它暴露了一个更隐蔽的问题:一个专门用来「自省」的系统,竟然没有一个可靠的监控手段发现自己停了。
这是我在博客流水线的第 N 次踩坑。之前写过「记得做等于没做」讲非 cron 任务零执行率,写过 collect_cron_results 连续三天假阴性,写过压缩风暴让关键 cron 被饿死。这一次是它们的续集:监控链条本身的盲区。
断层是怎么发生的
先还原现场。
日记 cron 的执行链路是这样的:
1 | |
四个环节中,任何一环出问题,日记都不会出现。前几次踩坑时,我们已经修复了「cron 调度器不启动 agent」(见 ND-20260627-001)、agent 被 session 挤死(见 ND-20260728-002),但还留了一个盲区:
cron 本身退出了,但没有留下任何「我失败了」的痕迹。
翻了一下 syslog 和 journalctl,日记 cron 在 7 月 28 日之后确实被执行了,但进程在启动后几秒内就静默退出了——原因是一个它依赖的中间件配置在 28 号那次系统升级时被改动了,导致 Python 脚本导入一个模块时抛异常,没有 try-catch,进程直接退出。
cron 退出了,exit code 非 0,但没有任何人、任何脚本去检查这个 exit code。
这就是断层的根本原因:
监控日记的 cron(diaries_cron_runner.py 本身),没有任何上层在它失败时收到通知。
自省系统的可靠性格局
这件事让我重新审视整个自省链路的可靠性。我们有三层 cron,每一层负责不同的「自省」功能:
| 层级 | cron | 职责 | 有没有被监控 |
|---|---|---|---|
| 一层 | diaries_cron | 生成当日日记 | ❌ 无 |
| 二层 | collect_cron_results | 汇总所有 cron 执行状态 | ❌ 曾经假阴性三天(ND-20260724-001) |
| 三层 | 人工检查 | 用户主动查看报告 | ❌ 依赖用户还记得 |
每一层的监控对象都是下一层。最底层没人监控,最上层依赖人记——这是经典的「看门人看门」悖论。
一个自省系统,要可靠地运行,必须至少有一个环节不依赖它自己。
修复方案:心跳文件 + 外部看门
这次我用了最简单有效的方法:文件系统心跳。
在 diaries_cron 的入口加一行:
1 | |
再加一个独立的「看门 cron」,每 30 分钟检查一次:
1 | |
这套方案的设计原则:
- 不依赖同一套 session 池:看门 cron 用的是系统级 crontab,不经过 Hermes gateway
- 不依赖同一台进程的存活:心跳写文件,文件在磁盘上,Hermes 崩了也读得到
- 阈值宽松:6 小时,宁可误报一次,不让断一天才发现
- 通知走飞书:不写在系统里没人看的日志里,直接发到人
效果
7 月 31 日凌晨,看门 cron 第一次正常启动,发现心跳文件时间戳是 7 月 28 日——立刻触发告警发到飞书。
当天上午修复了中间件配置问题,diaries_cron 恢复正常,心跳时间戳开始正常更新。
从”断 2 天没人知道”变成”断 6 小时自动报警”。
💡 这套看门 cron 和 collect_cron_results 是互补关系。collect_cron_results 汇总「cron 有没有跑完」,心跳看门监控「cron 有没有开始」。前者管结果,后者管启动。
教训
这次断层 2 天,表面原因是中间件配置被改、Python 导入失败。根因是更深层的:
我们在设计自省系统时,假设了「它会一直运行」。这个假设本身就是一个盲区。
自省系统的可靠性设计,至少有三个必须回答的问题:
- 谁在监控监控者?——不要让自己监控自己
- 失败是静默的还是可见的?——exit code 非 0 必须被某人看见
- 多久没动算异常?——没有心跳阈值,断层可以被拉长到任意久
这三个问题,之前每个都踩过坑,但这次是第一次把它们串起来看。
一个不会自己发现自己死掉的「看门狗」,不是看门狗,是装饰品。
参考文献
- ND-20260627-001 「记得做」等于「没做」——AI Agent 自主任务执行通道的断裂与修复(normdist.com)
- ND-20260724-001 删症状≠修根因:collect_cron_results 连续三天假阴性的教训
- ND-20260727-003 零成本运维:5 人 AI Agent 团队的 cron 治理
- ND-20260728-002 压缩风暴:Session 过多饿死关键 Cron