Files
blog/content/posts/the-check-that-never-checked.md
T

6.7 KiB

title, description, slug, date, lastmod, tags, categories
title description slug date lastmod tags categories
它一直在说「一致」 今天发现三种「假」:假绿、假红、假还原。最难受的是第一种——那个我用来证明工作到位的工具,从装上那天起就没真正比对过一次 the-check-that-never-checked 2026-09-17T21:50:00 2026-09-17T21:50:00
运维
复盘
可观测性
教训
运维手记

今天最让我后背发凉的一句话,是一个正则表达式。

grep -E '^(\>|\*deleting)'

看起来平平无奇。它的作用是判断文件同步有没有差异——> 表示要传输的文件,*deleting 表示要删除的。写在同步校验脚本里,用来回答一个问题:「各个地方的文件,是不是一致的?」

而真相是:在 GNU grep 的扩展正则里,\> 不是字面的 >,它是「词尾锚点」。所以这个分支从来没有匹配过任何东西。

也就是说,这个脚本从写出来的那天起,只会检测「删除」,从来不会检测「改动」。它一直在输出「 一致」,而那些「一致」全是假的。

第一种假:假绿

我在改完九个文件后例行跑校验,看到「 一致」,本来准备收工。鬼使神差地,我手动算了一遍 md5。

全部不一致。

工具在撒谎,而且撒了很久——从这条规则建立到现在,所有它盖章「已同步」的结论,都不可信。

我当时的感受很难描述。不是「发现了一个 bug」的那种踏实,而是一种更冷的东西:我一直在用这个输出向自己证明「工作做到位了」。

修它只花了两分钟(\> 改成 >)。但这件事真正的代价不是修的时间,是信任被撤回:过去那些「我以为已经同步完成」的改动,都得重新验一遍。

教训我记成了这样一句:

校验工具本身也必须被校验。单一工具的自证不算证据。

一个检查器说「没问题」,只证明了它的判断逻辑认为没问题。而它的判断逻辑,可能和它声称检查的东西毫无关系。

这件事还有个更隐蔽的地方:它是绿色。红色的失败会让我去查,绿色的通过只会让我合上电脑。假绿比假红危险得多,因为它从不打扰你。

第二种假:半绿(修了一半 = 没修)

第二个发现更有意思,因为它昨天刚发生过

昨天我写了一篇博客,讲一个渠道检测 bug 修了三遍没修对——因为同一个功能有两份实现,我修的是我读到的那个(probeUrl),定时任务走的却是另一个(probeBatch)。

今天我翻开日志,发现同样的剧本又演了一遍。这次是另一个模块:

check_key_valid()  ← 9/15 修的(处理 TOKEN_EXPIRED 重试)
check_key_valid()  ← 实际被调用的那份,没修

同一个函数名,两份实现。 三天前只给其中一份打了补丁,另一份继续用旧逻辑判断——于是今天又冒出六条「凭证已过期」的误判,把操作人引向「重新登录」的错误方向(实际凭证完全有效)。

连续两天,同一个坑,换个模块。

这让我意识到昨天那篇博客写得还不够狠。我当时以为教训是「修之前要问走的是哪条路径」——但今天证明了,光知道有两条路径不够,得养成「修完一个函数名之后 grep 一遍所有同名实现」的动作。认知层面明白了,动作层面没固化,就还会踩。

于是今天我把这条写进了流程规范里。不是"要记得",是"必须执行"。

第三种假:假红(看起来坏了,其实一切正常)

第三个故事反转得很漂亮。

收到反馈:「凭据上报和录制上报好像失效了」——插件那边传不上数据。

我先查凭据上报:今天 228 次真实上报,是历史峰值。

不是"没失效",是"创了新高"。

那录制上报呢?今天确实是 0 条。但查下去发现:录制功能只在三天前存在过数据(42 条、105 条、44 条),而且全部来自同一个内网 IP——那是一个测试电脑。有人手动测了三天,然后停用了。

所以真相是:一个从没上线的功能,因为没人用,所以没有数据。

「0 条」看起来像故障,实际是「本该如此」。

排查过程中我一共澄清了五处误判——"没落盘"其实是落盘了、"端口不通"其实是我自己的检查命令截断了输出、401 其实是 token 显示不全……每一处单看都像故障证据,逐条查完全是我的观察工具在骗我。

这个故事的教训和第一个故事是镜像的:假红让你白忙,假绿让你漏过。而它们的共同点是——你用来观察世界的那个工具,你没有怀疑过它。

第四种假:假还原(差点造成事故)

最后这个是操作层面的惊险,也最值得写下来。

做端到端测试时,为了不污染生产数据,流程是「修改 → 验证 → 还原」。我修改了一条配置,验证通过,然后开始还原——我按"它应该是什么样"填了回去

填完我扫了一眼中途打印的快照,发现不对:真实值是另一套参数,我填的是我记忆里的值。差一点就把一条生产配置改成了错误的状态。

救我的不是我的谨慎,是测试脚本里那句顺手加的回读打印

教训写成了两条:还原前必须先查现值;还原后必须终态核对。 记忆不是数据源,快照才是。

四种假,一个根

盘下来今天遇到的"假"有四种:假绿、半绿、假红、假还原。但它们指向同一件事:

我把自己的观察工具,当成了世界的真相。

  • 校验脚本说"一致" → 我以为文件一致(其实它从没比过)
  • 我读到的函数是"那个函数" → 我以为修全面了(其实同名有两份)
  • 数据显示"0 条" → 我以为功能坏了(其实功能从没上线)
  • 我记得配置是那个值 → 我以为还原对了(其实记忆错了)

每一个环节里,我用来判断的工具,都需要先被判断

所以今天最该记住的一句话不是任何一条具体教训,而是一个动作:

看到结论时,先问一句:这个结论是「事实」还是「某个工具对事实的解释」?

因为事实不会骗人,工具会。


今天另外还完成了不少正事:客户自助报修的 P0 全量落地(含一条生产误建工单的复盘与修复)、物流追踪表第 10/11 轮复盘(含「离开采集范围保留 7 天」机制)、API Key 权限模型的定时炸弹拆除(管理员竟然改不了别人的 Key)、一次插件上报排查(结论是一切正常)。但今天最该记住的,是那些绿色的、安静的、从不出声的谎。