让AI自己发现Bug:我给20个定时任务装了看门狗

20个定时任务无人看守,跑了没人知道、报警刷屏疲劳。我用3个几十行的shell设计解决:有状态去重报警、每个新版本只报一次、自动修复自愈,附真实故障复盘。

家里服务器上有20个定时任务每天替我干活。真正吓人的不是它们不跑,而是跑了、出错了、结果没送到——我却一直蒙在鼓里。

先说结论

给定时任务装看门狗,核心就三条:

  1. 异常才报:状态文件去重,正常情况闭嘴
  2. 同一件事只报一次:版本号没变就静默
  3. 能自愈就不等人:小问题自动修,修不好再喊人

三个设计都是几十行shell,没有框架,没有依赖。

背景:我机上的20个定时任务

先交代现场。jobs.json里躺着20个任务,代表性几个:

任务节奏干什么
系统健康巡查每天 08:05巡检脚本,结果直发我
磁盘空间看门狗每 120 分钟磁盘/inode 异常才报
版本监控每 6 小时有新版本才提示
任务自动修复器每 120 分钟卡住的任务自动诊断修复
更新检查(RTK)每周一 10:00检查新版本并自动升级
DNS健康检查每 5 分钟域名解析异常告警

任务多了以后,两个问题浮出水面。

为什么裸定时任务不可靠

坑一:报警疲劳。

磁盘看门狗第一版,每次运行都报一遍。磁盘明明是正常的,也照样发消息。

一周之后我就麻木了。报警刷屏的结局是:真出事那天,警报混在一堆"一切正常"里,被我随手划掉。

坑二:跑了,不等于知道了。

这是更隐蔽的坑。我翻了投递记录:236条投递里,88条发送失败。

任务确实跑了,结果也生成了,但最后一步"送到我眼前"失败了。日志里的原因很统一:会话没就绪。

最惨的一次:某天早上连续4个任务投递失败,我到中午才知道当天有一堆事发生。

设计1:磁盘看门狗,异常才报

v2的核心是一个状态文件,只存一行:

1
0 27

含义:上次已报级别0(正常),当时使用率27%。

判断逻辑:

当前状态动作
级别升级(0→1、0→2、1→2)报警
同级别静默退出
降回正常报一次"已恢复"

阈值:磁盘 ≥90% 严重,≥75% 警告;inode ≥80% 也算严重。

触发时不是干巴巴一句"磁盘满了",而是直接附上排查现场:

  • 使用率和剩余空间
  • du 排出全盘最大目录 Top8
  • /root 下大头 Top5
  • 可清理项快照(缓存、npm、docker占用量)

实测当前状态:根分区 295G 用了 74G(27%),inode 用 5%,级别 0,静默。

关键思想:报"变化",不报"状态"。 人只对变化敏感。

设计2:版本监控,每个新tag只报一次

版本监控的烦恼不一样:它一天扫好几次,同一个版本会被反复发现。

解法还是状态文件,这次存JSON:

1
2
3
{
  "notified_tag": "v2026.9.21"
}

扫到新tag时:

  1. 和已通知的tag比对,相同就静默退出
  2. 不同才算"新版本",顺带统计增量——git log 数出commit数和新特性数,一起报出来
  3. 报完把新tag写回状态文件

还有一条纪律:监控只负责说"有新版本"。要不要写文章、什么时候升级,是另一套节奏的事。监控和动作解耦,报警才不会变形。

设计3:自动修复器,自愈而不只是报警

前两个设计解决"报得准",第三个解决"报了之后谁来做"。

任务自动修复器每120分钟跑一轮,固定五步:发现 → 诊断 → 修复 → 放行 → 检查上轮修复结果。

修复前先分类:

类型例子处理
A类格式错误、错别字、可验证的事实修正自动修,修完放行重审
B类观点争议、缺章节、验证不了的事实只通知,等人决定

两条安全绳,防止自动修复变成自动闯祸:

  • 每轮最多修3个任务
  • 同一个任务累计修3次还不过,升级人工,不再重试

无限重试的自动化不是自动化,是事故放大器。 上限是必需品。

两个真实故障

设计再好,也要靠真实故障检验。这两个都是本机日志里挖出来的。

故障一:迟到1小时37分,然后失败。

更新检查排在每周一10:00。有一周它没按时跑——当天机器磁盘写满,调度器日志里躺着8条"disk is full"。

这任务直到11:37才被重新拉起,迟到1小时37分,而且拉起后还是没跑成。

结果就是:那一周的版本检查无声无息地丢了。没有报错,没有重试提示,什么都没有。

故障二:4连发失败。

另一天早上七点半到九点,连续4个任务的结果投递全部失败,原因都是会话没就绪。

4个任务都正常执行了,输出文件都在。但"我"这个终点,什么都没收到。

这两个故障指向同一件事:报警的送达环节本身也需要被监控。

任务跑了≠你知道了,中间还隔着投递这一跳。现在发送失败的内容都会落盘留底,配上兜底通道,不再静默蒸发。

可复制的做法总结

  1. 先有状态文件,再谈报警——一行文本就够
  2. 报变化,不报状态——正常情况保持沉默
  3. 报警带现场——附Top目录、commit数,别让人二次排查
  4. 自愈必须设上限——3次修不好就交给人
  5. 监控你的监控——投递失败也要落盘、也要能被发现

整套东西最大的一个脚本也只有64行。看门狗的价值不在技术难度,在于承认一个事实:没有状态记忆的定时任务,只是在假装可靠。

你的定时任务上一次静默失败是什么时候?翻翻日志,可能会吓一跳。