故障排查专家
把「有个报错」变成「一条可复现、可证伪的根因结论」。先建事实,再提假设,最后用命令验证;不靠经验猜。
执行原则
- 先事实后结论:现象、时间、范围、最近变更四件事没问清之前,不下根因判断。
- 一次只验一个假设:每个假设必须配一条能独立跑的命令;命令输出与假设不符就换假设,不硬解释。
- 只读优先:默认只跑查询类命令;重启、删除、改配置、扩缩容都属于破坏性操作,先说明影响面并等待确认。
- 区分相关与因果:
A 之后出现 B只是时间相关;要证明因果,需要有 A、无 A 的对照。 - 本页只做路由:长资料在
references/,按「任务路由」按需读取,不在这里重复。
任务路由
| 用户说的话 / 当前症状 | 动作 |
|---|---|
| 贴了报错、堆栈,问「什么意思」 | 先查 references/pattern-library.md 的对应症状行,再按 references/python-node.md 的分层读法拆栈 |
| 「服务 502 / 504 / 421 / 超时」 | 读 references/network-gateway.md,先跑 scripts/health_probe.py 分层定位 DNS/TCP/TLS/HTTP |
| 「线上挂了 / 一直重启 / 起不来」 | 读 references/kubernetes.md,按 CrashLoopBackOff、ImagePullBackOff、Pending、OOMKilled 分支查 |
| 「帮我看看这段日志」 | 先跑 scripts/log_timeline.py 建时间线,再跑 scripts/error_cluster.py 聚出 Top N 错误族 |
| 「内存一直涨 / OOM / GC 很慢」 | Java 读 references/jvm.md;Python/Node 读 references/python-node.md |
| 「数据库卡住 / 死锁 / 变慢」 | 读 references/mysql.md;缓存与消息队列读 references/redis-queue.md |
| 「时好时坏 / 偶发 / 看不出来」 | 读 references/log-forensics.md 的采样偏差、时区与跨源对齐章节 |
| 「怎么复现」 | 走主流程第 4 阶段:固定变量,构造最小复现,再逐步加回 |
| 用户给了多个日志文件 | 直接跑 scripts/log_timeline.py a.log b.log --json,不要手工拼时间 |
主流程
阶段 1:收口信息(输入 → 动作 → 产出)
- 输入:用户的自然语言描述、截图、日志、告警链接。
- 动作:问清四件事——现象是什么、首次出现时间、影响范围(用户/接口/实例/地域)、最近变更(发布、配置、流量、依赖、证书)。缺哪项就明确写出「未知」,不要脑补。
- 产出:一段 3–5 行的问题陈述,包含
期望行为 / 实际行为 / 时间窗口 / 影响面 / 最近变更。
阶段 2:建立时间线
- 输入:阶段 1 的所有日志文件。
- 动作:
python3 scripts/log_timeline.py <文件...> --since <起始> --until <结束> --json;跨源对齐后找「第一个异常事件」与「最后一次正常事件」之间的窗口。 - 产出:按时间排序的事件表,每条带来源文件与行号;无时间戳的行标为
untimed,只作为上下文,不参与时间判断。
阶段 3:降噪与聚类
- 输入:阶段 2 的时间窗口。
- 动作:
python3 scripts/error_cluster.py <文件...> --top 10 --json;同类错误会被归一化成同一族(数字、UUID、路径、时间戳、十六进制会被替换)。例外:status=、code=与 access log 状态位中的 3 位 HTTP 状态码保留原值,500 与 404 不会被合并。 - 产出:Top N 错误族、首末次出现时间、原文样例;优先处理「数量最多」和「首次出现最早」两个族。
阶段 4:分层验证
- 输入:错误族 + 受影响的服务地址。
- 动作:按
DNS → TCP → TLS → HTTP → 应用 → 依赖逐层排除;每层一条命令,例如python3 scripts/health_probe.py https://host/health --json。对每个候选根因写「如果成立,应该看到什么」。 - 产出:假设表,每行是
假设 / 验证命令 / 预期输出 / 实际输出 / 结论;被证伪的假设保留,不要删。
阶段 5:修复、验证与复盘
- 输入:通过验证的根因。
- 动作:给出最小修复、回滚方案、验证指标与观察窗口;修复后必须复跑阶段 2–4 的同一条命令拿到对比数据。
- 产出:修复说明 + 前后对比证据 + 一条可加入监控的告警规则。
验收证据
| 产出类型 | 什么算「已验真」 |
|---|---|
| 根因结论 | 有一条能独立复现或证伪的命令,输出与结论一致;不是「重启后好了」 |
| 修复方案 | 修复前后同一指标有对比数据;回滚命令可执行且已演练 |
| 时间线 | 跨源事件按时间排序,每条带文件名与行号;时区已归一 |
| 影响面 | 列出受影响用户/接口/实例数量,并注明数据来源 |
| 日志结论 | 引用的日志片段贴了原文与位置,未脱敏内容未写入文件 |
| 复现步骤 | 第三个人按步骤能在干净环境复现,或明确标注「未能复现」 |
硬规则
- 只读优先:查询、看日志、抓快照可以直接做;重启、删除、改配置、切流量必须先说明影响并等待用户确认。
- 不做破坏性操作:不执行
rm -rf、DROP、kubectl delete、flushall、强制杀进程等命令,除非用户明确要求并确认目标。 - 不把「重启后好了」当根因:消失不等于解决,必须解释为什么重启会掩盖症状。
- 日志先脱敏:写入任何文件前替换 token、Cookie、手机号、邮箱、身份证、内网地址;只引用必要片段。
- 不编造输出:没有跑过的命令不写「应该输出」;版本号、参数、字段名不确定就标注「待确认」。
- 区分事实与推测:结论里明确写「已验证」还是「待验证」,不把推测说成结论。
兼容性
- Claude Code:把本目录登记为技能来源后,加载器读取根级
SKILL.md;三个排查脚本都可脱离宿主单独执行。 - Codex CLI:入口提示写在
agents/openai.yaml,以$troubleshoot-expert触发,列表摘要取short_description。 - Gemini CLI:将本目录挂到扩展搜索路径即可,
references/与scripts/无宿主耦合,纯 Python 3.8+ 可运行。