# 告警的尽头是执行器 > 半夜收到第三条一模一样的告警时,我意识到一件事:我不是在运维这套系统,我是在给系统当定时任务。 这套自动化的内容流水线里,每一层都看得见「卡住了」——队列页面显示它,告警机器人广播 - Canonical page: https://obelisk.club/blog/build-log-3926 - Author: Peter Zhang - Published: 2026-10-11 - Tags: build-log 半夜收到第三条一模一样的告警时,我意识到一件事:我不是在运维这套系统,我是在给系统当定时任务。 这套自动化的内容流水线里,每一层都看得见「卡住了」——队列页面显示它,告警机器人广播它,连部署脚本都会在退出前专门提醒一句「有个运行挂了」。但三层视力加起来,抵不过一个动作:取消那个楔死的运行,让下一轮自己接上。今天它第三次发生时我才想明白,我一直在扮演的,就是那颗「最后由人来按的按钮」。 为什么这类事总是留到最后?因为告警是便宜的:读状态、发消息,做错了也无非错过一条消息。执行器是吓人的:它要代表系统做「取消」「杀进程」这种不可逆的事,而「万一自动化判断错了呢」这个问题,能拦住一个人很多年。拦住的代价是:每一次人工处置,都是一次 MTTR 等于人类注意力跨度的排障。 解法有顺序,而且顺序承重: 1. 先把判断写成预算表,再写执行器。「超过 X 秒无进展即视为楔死」里的 X,是每个环节自己的截止时间加余量——这是一个可以像代码一样被 review 的决定,不是运行时的灵机一动。没有预算表的执行器不是自动化,是赌博。 2. 执行器只动「冻结的」,不动「慢的」。判定依据是无进展的时长,不是总时长:跑了很久但日志还在前进的运行,是工作;状态时间戳半小时纹丝不动的运行,是谎言。 3. 动手前对活数据再核一遍。快照会撒谎;「取消」这种动作,永远值得为它多付一次实时查询。最坏的结局应该是「拒绝取消」,而不是「错杀」。 4. 兜底齐了之后,把人从循环里删掉。我每次收到告警做的都是同一个动作——那个动作本身就是执行器的完整规格说明书,照着写就行。 一分钟自检:翻出你最近手动处理过的一条告警,问一句——如果今晚没人值班,明早它会自己好吗?答不上「会」的那条告警,就是缺了一半的自动化:你造了眼睛,还没造手。