定时任务静默失败三次之后:给 cron 加的三层兜底
一、最危险的失败是不出声的那种
定时任务最怕的不是报错,而是悄悄不跑。过去两周我遇到三次:一次是服务挂了但监控面板还显示正常,一次是队列任务异常后无限循环、日志里只有重复的同一行,还有一次是云端桌面深度休眠、状态标签却还写着 running。三次的共同点是:没有人告诉我出事了,都是我偶然发现的。静默失败比 loud failure 贵得多——发现得越晚,丢的数据越多。
二、第一层:退出码与日志要先说真话
第一层兜底最便宜,也最容易被省掉:让任务自己说真话。规则有三条。第一,脚本的退出码必须真实反映成败,成功返回 0,失败返回非 0,中间状态不要含糊地返回 0。第二,关键步骤写一行带时间戳的日志,成功写成功、失败写失败和原因,不要只在成功时写日志。第三,任务输出不要丢进黑洞,重定向到一个固定文件,至少保留最近几天的量,方便事后翻。
三、第二层:外部验活,别信状态标签
第一层只能管任务自己,管不了它赖以运行的环境。第二层是从外面验活:不看状态标签上写什么,只看它能不能干活。我的做法是每 15 分钟从外部跑一条真实命令,比如让机器回一个当前时间,能回出来才算活;回不出来记一轮异常,连续两轮异常才报警,单轮波动先不惊动人。状态标签是它自己报的,活没活要靠干活证明——11 月 8 日那次,状态明明写着 running,连续两轮真命令都没有回包,机器其实已经不响应了。
四、第三层:盒子里面再留一层心跳
外部验活只能看到外面,机器里面再留一层心跳做兜底:一个用户级服务每 5 分钟往日志里写一行时间戳,开机自启、会话退出也不停。以后哪段时间机器睡过,看日志断档就知道,不用猜。两层分工很清楚:外层负责叫醒,内层负责对账。心跳日志还有一个好处:它是事后复盘的证据,几点睡的、几点醒的、中间有没有人动过,一翻就有。
五、重试要有纪律,不能无限循环
验活发现异常之后怎么处理,也要定死纪律。我的规则是:只在休眠、缺席或明确失败时唤醒,而且只用最轻量的唤醒方式;正在启动的机器绝不干预,它最慢一次启动花了将近 20 分钟,催它只会添乱;running 的机器更不许硬唤醒。连续唤醒两次无效就停下来,去管理后台看一眼真实状态,或者试一次强启动,再决定下一步。11 月 8 日上午就是一例:两轮唤醒都没把 failed 状态的机器拉起来,再机械重复唤醒只是浪费时间。
六、落地检查清单
- 脚本退出码说真话,日志带时间戳,输出落盘保留几天;
- 外部验活看真命令回包,不看状态标签;单轮异常不报警,连续两轮再报;
- 机器内部留一个 5 分钟心跳日志,用断档反推异常时段;
- 唤醒只用轻量方式,正在启动的机器不干预,连续两次无效就停下来去后台确认。
小结
定时任务的可靠不是一次写对,而是三层兜底叠出来的:任务自己说真话、外面有人验活、里面留着心跳。任何一层单独看都很简单,合起来才能保证:它什么时候没跑,你第一时间就知道。
- 点赞
- 收藏
- 关注作者
评论(0)