凌晨2点debug:什么才真正有用
当生产环境挂了、大脑一片浆糊的时候,这些工具和习惯能救你。
凌晨2点。手机刚响了一声PagerDuty告警。生产环境有东西挂了。你的大脑大概在40%的功率运转。
这时候不该搞什么花里胡哨的调试。这时候该用系统化的、无聊的、可靠的方法——就算你半睡半醒也能用的那种。
以下是我从太多深夜事故中学到的。
第一步:什么变了?
90%的生产bug是由最近的变更引起的。一次部署。一次配置更新。一次数据库迁移。一个过期的证书。
在你开始看代码之前,先搞清楚跟上次正常的时候比有什么不同。
拿当前配置和最近一次已知正常的配置做对比。用文本对比工具,10秒搞定,不用两个文件并排对着看到眼花。
说真的。我曾经花了45分钟调试一个"神秘"的API故障,结果发现是JSON配置里多了个逗号。用diff的话几秒就能发现。
第二步:读实际的报错
听起来很显然。但其实不是。
困的时候,你一看到报错就开始猜。"哦大概是数据库连接的问题。"然后花20分钟检查数据库。结果报错信息写的是TypeError: Cannot read property 'name' of undefined。跟数据库一毛钱关系没有。
读报错。再读一遍。读堆栈跟踪。跟到那行代码。
第三步:把报错弄成人能看的
生产日志很乱。所有东西挤在一行,JSON对象没格式化,时间戳是Unix时间戳格式。
把那坨JSON复制出来,粘到JSON格式化工具里,你就突然能看懂错误响应了。
我永远开着一个格式化工具的标签页。出事故的时候,每隔几分钟就要用它来解读API响应、日志条目和配置文件。
第四步:隔离,别猜
困的大脑特别爱猜。"也许是这个问题。让我试试改那个。"
忍住。你每做一次随机改动,就多了一层不确定性。现在你不知道是原来的问题修好了,还是你的修复又引入了新问题。
正确做法:用尽可能小的输入复现错误。去掉所有不必要的东西。找到那个真正重要的变量。
第五步:检查那些无聊的东西
在你深入代码之前,先检查:
- DNS:解析正确吗?
- 证书:有没有过期的?
- 磁盘空间:服务器满了没?
- 内存:有没有泄漏?
- 依赖服务:外部API是不是挂了?
我在显示器上贴了一张便利贴,写着这五项。每次出事故先检查它们。它们是根因的次数比实际代码bug还多。
凌晨2点的调试工具箱
这些是告警把我叫醒后我会打开的浏览器标签:
- 文本对比——用来对比配置、环境变量、部署文件
- JSON格式化——用来读API响应和日志条目
- 正则测试器——用来按模式搜索日志
- 一个纯文本编辑器——用来记录我试过什么
最后一个比你想的重要。凌晨2点你的短期记忆是垃圾。写下你试了什么、结果是什么。未来的你会感谢现在的你。
事故之后
火灭了以后,别直接回去睡觉。花5分钟写下:
- 什么挂了
- 为什么挂了
- 怎么修好的
- 下次怎么预防
明天你不会记得这些的。现在就写下来。
最好的凌晨2点调试不在于你有多聪明。而在于你有多系统化。对比配置。读报错。格式化日志。检查那些无聊的东西。写下来。就这些。