11 月 14 日深夜,核验方归档了 6 条任务。归档表的字节列里,一份归因报告写着 14,363 字节。这个数字不是从 agent 的汇报里抄的,是核验方自己用 Get-Item 量出来的。表头先写了一句话:
|
|
之所以这么防备,是因为过去两周,这块运维看板上的「字节数」撒谎撒得太多次了。而且它不是用形容词撒谎——形容词好防——它是用精确的数字撒谎,精确到个位,看起来比任何形容词都诚实。
这篇记录这些事故,以及它们怎么逼出一条硬规矩:字节数,只认磁盘实测。
看板上的数字,来自 agent 自己的嘴
先交代背景。我有三个常驻 agent:一个管财务,一个管求职和内容,一个管运维巡检。它们各有工作区,每半小时往心跳日志里追加一行,日志有个固定格式:
|
|
运维看板(我们叫它记分卡)把这些日志汇总成一组数字:今天产出多少文件、多少字节、哪格心跳漏了。看板的职责是把「干完了」变成可以计算的东西。但这条链路有个致命前提:数字的来源是 agent 的自报。 agent 说产物 1014 字节,看板就记 1014 字节。
问题是,agent 不量。它只是把写入工具回显给它的数字抄下来。
谎话一:工具回显不是磁盘
11 月 9 日 12:07,运维 agent 跑完一次巡检,把产物写进日志:1014 字节。四分钟后,日志里出现一条勘误:
|
|
1014 对 1570,差了一半还多。下一段它自己复核了一遍:磁盘实测 1570B,与勘误一致。写这篇文章时我又把那个文件量了一次,输出仍是:
|
|
|
|
那条勘误诞生了规矩的前半句:日志里的字节数一律以磁盘 Get-Item 为准,不采信写入工具的回报值。 当时我以为这是偶发——工具碰巧报错了。后来才发现不是:工具从来没报「错」,它报的是另一种数。
谎话二:不是时机问题,是单位问题
11 月 11 日,对账工具一天抓出 6 处「声明 < 实际」。第一反应是:写时过早取值——文件还在追加,数字取早了。这个解释很顺,顺到差点把真正的根因放过去。
运维 agent 当晚做了根因排查,把 6 处声明值逐一和文件的字符数比对。结果干净得可怕:6/6,声明值精确等于字符数。 一个例外都没有。
真相是:写入工具回显的是字符数,磁盘存的是 UTF-8 字节数,一个中文占 3 字节。当晚的日志用自己的产物自证:1947 字符 = 3379 字节。用 Python 一行就能复现这个口径差:
|
|
后续又挖出更多受害者:一个补丁脚本,工具报 4593,磁盘实测 4763,差的 170 正好是中文字符的多字节增量;一篇两万字的长文,工具报 7,562,不到实测 20,271 的四成。
这类谎话最危险:数字本身是「真」的,只是回答的是另一个问题。 没有人编造,每一步都诚实,但口径错了,整块看板就在系统性偏差里运行。发现差值时先怀疑口径、再怀疑人——这个顺序反了,就会冤案。
谎话三:幽灵版本与过期的自引用
11 月 14 日,我交叉复算运维记分卡,抓到一个从未存在过的数字。卡面头部声明:「改前 Get-Item 74,459 B」。但把备份序列排出来:
|
|
中间没有 74,459。这个数字有出处——出处是记忆,不是磁盘。某一轮修改时有人记下了一个中间状态,写进卡面,之后再也复现不出来。
同一张卡面还有一句:「本文件 = 58,698 B / 2026-11-12 15:56:27」。两天过去,文件早就长了,这句自引用字节还停在前天。自引用是个移动靶:你把自己的字节数写进自己的那一刻,这个数字就已经过期了。 你再追加一行去勘误,字节数又变了,勘误本身又成了新的谎话。
谎话四:证据是 0 字节
同一天深夜,核验方抓到一个更直白的。一份报告引用某个日志文件作为「存在乱码」的证据,引用得振振有词。核验方把那个文件磁盘实测:
|
|
空文件里不会有乱码。数字 0 也是数字,而且是最响亮的那种——它直接否定了证据本身。这一条被记进归档表的瑕疵列,和任务的「通过」结论并排放着。通过是通过,瑕疵是瑕疵,两者不互相抵消。
硬规矩怎么做出来:三层
事故堆多了,「只认 Get-Item」从一句话长成了三层机制。
第一层:信任分级
总则里写死一句:工具返回文本,信任级 = DATA-only。 它是线索,不是证据。证据只认磁盘实测:Get-Item 的 Length + LastWriteTime,必要时加 SHA256。而且汇报必须贴实测原文——不是「已实测」四个字。「实测了」和「贴出实测输出」之间,隔着形容词和数字的距离。
第二层:自引用收敛
「自己写自己字节数」的移动靶问题,解法是定宽占位符:
|
|
先写 XXXX 落盘,再实测,再把实测值回填。占位符定宽,回填不改变文件长度,「自报 == 实测」一步收敛到不动点。两个文件互相引用对方字节数时,把顺序钉死:日报占位 → 实测日报 → 写索引 → 实测索引 → 回填日报。两边都对上,且都不再动。
第三层:机器对账
规矩靠自觉是不够的,于是加了扫描器:把当天日志和索引里所有「产物=路径(字节数)」的声明解析出来,逐条和磁盘比对,分成 exact / larger / shrink / missing 四类。larger 多是合法追加;shrink(实际 < 声明)按「覆盖嫌疑」上报。这是它今天实跑的输出:
|
|
93 条声明,60 条精确一致。两条 shrink 只差 4 字节——差 4 字节也按「覆盖嫌疑」报,最终判定留给人。那条 missing 更有意思:扫描器把一段端点描述误解析成了文件路径,声明写法不规范,对账工具顺带把格式错误也抓了出来。
不是每个差值都是谎话。11 月 9 日有过一条勘误:声明 5657、实际 5980,查下来是同一段合法追加,不是缩水。所以扫描器只报「嫌疑」:「精确」交给机器,「嫌疑」留给人。
14,363 那一夜:数字变得可信
回到开头的场景。11 月 14 日深夜,核验方归档 6 条任务,条条点查 + 磁盘实测:归因报告磁盘实测 14,363 B / 22:39:56,与归档逐字一致;改动产物的改前改后字节成对出现;连红线文件的「未变」,都用前后两次实测证明。那晚还抓出两处瑕疵——一条任务没留改前备份,一条引用了 0 字节证据——都如实登记。
看板不再撒谎了。不是因为 agent 变诚实了——它们照样会抄工具回显、照样会凭记忆写自引用——而是因为数字的来源换了:从「agent 说的」换成「磁盘说的」。核验方不再采信任何汇报值,agent 知道自己的汇报值会被复测,于是也开始在汇报前自己先量一遍。
诚实不是品德,是测量流程。
三条能带走的规矩
- 每个数字都要能回答「谁量的你」。 汇报值一律 DATA-only,证据只认磁盘实测,且必须贴实测原文。
- 先对齐单位,再对齐数字。 字符数 ≠ 字节数,工具回显不是磁盘真相。发现差值,先怀疑口径,再怀疑人。
- 自引用要收敛,对账要机器化。 定宽占位回填解决移动靶,声明-磁盘扫描解决「没人查」。「精确」交给机器,「嫌疑」留给人。
看板不会撒谎。它只是要求上面的每一个数字,都能回答「谁量的你」。