用途:现象说不清、原因不知道、也不知道错在哪一层 —— 把它缩小到一层、一个环节、一行。
覆盖:软件、站点、脚本、自动化流程。有明确报错的除外。
产出:一句「问题在这一层」+ 一条能重复触发的路径 + 已经排除掉的范围。
拿到就能跑:先别改。 改动会毁掉证据,这是排查里最常见的自伤。
问之前先做一件事:把现在的现象原样记下来。 什么时候、做了什么操作、看到什么。改了之后就再也回不到这个状态。
| # | 问什么 | 怎么问出口(原话) | 判据 | 答不上来时 |
|---|---|---|---|---|
| Q1 | 能稳定复现吗 | 「用刚才那套操作再做三次,是不是三次都出现?」 | 三次都出现 → 能复现,转 Q2;时有时无 → 路径 C | 让他把操作写成步骤,你照着做;你这边不复现、他那边复现,本身就是一条信息 |
| Q2 | 知道什么时候开始不对吗 | 「上一次它是好的,是什么时候?」 | 说得出时间点 → 路径 B;说不出 → Q3 | 翻最近一次正常的结果,看它和现在差在哪 |
| Q3 | 那前后有改动吗 | 「最后一次正常之后,改过什么?代码、配置、依赖、数据都算。」 | 有改动 → 路径 B;没有 → 路径 A | 查文件修改时间、版本记录、部署记录,别靠回忆 |
| 条件 | 路径 |
|---|---|
| Q1 = 能复现,Q2 = 知道时间点 | B · 变更回溯 |
| Q1 = 能复现,Q3 = 有改动 | B · 变更回溯 |
| Q1 = 能复现,其余无线索 | A · 二分定位 |
| Q1 = 不能复现 | C · 记录等待 |
能复现但不知道从哪下手时用。核心是每次切掉一半,而不是「猜一个试试」。
做法:
判据:每做完一步,范围必须明显变小。 如果做了一步范围没变小,说明那一步没切在有效的分界上,换一个切点。
⛔ 不要同时改两个地方再看结果。改了两个,就不知道是哪个起的作用,等于白做一轮。
知道时间点或有明确改动时,这条路最快——问题几乎总在最近变过的地方。
做法:
如果全部回退后问题还在 → 说明它本来就在,只是现在才被发现。这跟「改坏了」是两回事:前者要查的是「什么时候引入的」,后者要查的是「改了什么」。判断错了方向,会一直在最近的改动里绕圈。
时有时无最难受。这时不要猜着改——改对了也不知道为什么好,改错了会引入新问题。
做法:
⛔ 不要因为「这次没出现」就宣布修好了。没复现不等于不存在。
现象:<原样记录,含时间与操作>
能否复现:能(步骤…)/ 不能
路径:A 二分 / B 变更回溯 / C 记录等待
已排除:<哪些层、哪些改动,各自用什么方法排除的>
判断:问题在 <哪一层 / 哪个环节>
下一步:<具体动作>
symptom: <原始描述>
reproducible: true|false
path: binary|change|wait
ruled_out: [{layer, method, evidence}]
located_at: <层 / 环节 / 文件:行>
confidence: confirmed|likely|guess
next_action: <具体动作>
confidence 必须是三档之一。「guess」也算合法结论——比装作确定好,它告诉下一个人该先验证什么。
问题在 X 层,已排除 A、B;下一步验 C。 或 暂不能定位,已加记录等复现。
⛔ 不要说「应该是缓存问题」就结束。没有排除记录的判断,都是猜。
2026-11-06。方法与工具无关;三条路径的选择判据(能否复现 / 是否知道时间点)通用。与所执行系统的既定标准冲突时,以那个系统的标准为准。