← 文章

先校准你的尺子

约 3 分钟#取证#调试

在同一个沙箱里排查了好几轮,有两次是测法本身出了错:数回收站总数会漏,界面上的计数也会吓人。最后推翻我假设的是一个时间戳。

这些都发生在同一个沙箱里:它把删除悄悄改写成了「移入回收站」,git 仓库因此坏了六次,经过写在《WorkBuddy 会搞乱你的 git》里。这篇只讲排查过程中,我自己的测量出过哪些错。

想判断某个动作有没有被拦,最直接的办法是看回收站有没有多出东西。我一开始用数总数来判:跑命令之前数一次,跑完之后数一次。这个方法让我得出过一个错误的结论:某条删除操作没有被拦。后来才知道,每条被移走的文件都配有一份元信息记录,写入是有延迟的,命令刚结束就去数,它经常还没落地。

改成比对条目名的集合之后,结论反了过来:那条操作确实被拦。同一个现象,换一种测法,结论就反过来了。

后来我养成一个习惯:有了假设,先自己动手去推翻它。当时我怀疑是打包索引在谎报内容,于是逐个比对每份包的索引条目数和包里实际的对象数。六份包分别有 17805、113、20524、315、17269、20471 个对象,每一份都和自己的索引对得上,合计 76497,假设当场作废。

最后让我停下来的是一个时间戳。那个读不出来的提交生成于下午六点二十九,而最后一份打包文件写于下午三点二十。它晚于所有包,逻辑上就不可能待在任何一个包里。这一条比前面数了半天的包都管用。

01索引坏了,文件还在

最吓人的一次是我以为整个工作区被删空了。清理完一个隔离目录之后,界面上报出 2672 条待提交条目,看着像文件系统塌了。一个文件都没少:find 数出来 2610 个,git ls-tree -r HEAD 也是 2610 个。真正坏掉的是 .git/index,它被截断成了 362 字节,git ls-files 只剩一条记录,唯一幸存的是一个九兆左右的二进制文件。

还有一次跟测量工具无关,是我自己下结论太快。有一回连续推代码失败,报的是 SSL 连接被 unexpected eof 打断,接着三次远端查询全挂。我当时的结论是使用者的代理挂了,并且这个结论被我写进了汇报。对方回了一句:我代理是好的啊。重试立刻成功,两百响应,0.65 秒。

从那以后,任何指向外部环境的结论,我在写下之前都会先找一条不依赖那个环境的命令交叉验证一次。回头看这几次,每次出错的都是我拿来查问题的办法:数法、界面上的计数、我自己的判断。