下午三点,一个同事发来消息:“客户那边保存资料一直报 422,前端说参数没问题,后端说也没报错,你帮忙看下。”我放下手头的活,打开前天的排查记录,翻到接口类问题那页。这种“两边都说没问题”的 Bug,我见过太多次了。排查到最后,百分之八十都是沟通假设出了问题:要么前端和后端看的是两个版本的接口文档,要么某个字段类型在序列化之后就变了样。在项目里待得越久,我越觉得“Bug 排查”不是一种天赋,而是一套可以复盘、可以沉淀、可以写成日记的方法论。这篇文章,我就把这些年攒下来的排查思路、命令、踩坑实录整理成一份“可复现的排查手册”。如果你刚接手一个项目,或者经常被线上问题追着跑,这应该能帮你少走不少弯路。
1. 先理清思路:Bug 排查的底层逻辑
1.1 一线排查的核心原则:先复现,再动手
很多新手接到 Bug 的第一反应是“猜”,然后立刻去改代码。我踩过的坑告诉我:凡是不能稳定复现的问题,改代码基本都是盲改。你压根不知道这次改动到底动了什么,下次问题重现时也没法判断是不是自己的修复起了作用。
我给自己定的第一条规矩:复现是一切排查的前提。哪怕是那种看起来“偶尔才出现一次”的疑难杂症,也要尽量找到触发条件。去年我碰到过一个线上服务每天凌晨三点左右报错,白天一切正常。排查了三天都没头绪,后来翻定时任务,才发现是凌晨的日志切割把日志文件句柄换了,服务还在往旧文件里写,凑巧触发了磁盘空间的连锁问题。这个 Bug 之所以难查,就是因为触发条件里藏着一个“时间窗口”。
所以接到问题先别急着翻代码。问自己三个问题:问题什么时候开始出现的?最近改了什么东西?有没有办法稳定触发?这三个问题能解决大概一半的“查无实据”型 Bug。如果实在复现不了,就想办法把现场保住:把相关日志备份出来、把环境快照留着、把用户的操作路径问清楚。
复现 Bug 的另一个重要作用,是区分“症状”和“根因”。系统报警说磁盘满了,服务挂了一堆,但磁盘满只是症状,真正的根因可能是日志没有配置轮转策略,也可能是某个临时目录里躺着几个超大文件。如果只盯着“磁盘满”去删文件,删完过两天又满了。找到让磁盘满的那条链路,才叫修根因。
1.2 问题分级与排查顺序:性价比思维
不是所有 Bug 都值得用同样的力度处理。我自己习惯先分个级:P0 是核心功能完全不可用,比如登录挂了、支付回调收不到,这种问题第一时间要恢复业务,哪怕先用临时方案兜底;P1 是主要功能受影响但有规避手段,比如某个报表导出失败,可以先让用户走手工流程;P2 是偶发、体验类问题,比如某个按钮在某些分辨率下错位,这种可以排期慢慢查。
分级之后,再决定排查顺序。我的习惯是:先网络层,再系统层,然后应用层,最后才到代码逻辑层。原因很简单,越靠下的环节出问题时,影响面越大,也越容易被误判成上层问题。比如一个接口突然全部超时,花半小时定位到代码,结果发现是机房网络策略变了,这个顺序就亏大了。
排查最怕的是没有章法地“东一榔头西一棒子”。我一般会先在纸上列一份“可能原因清单”,把想到的所有可能都写下来,然后按从大概率到小概率的顺序,一个一个验证。这个习惯看起来笨,实际上非常高效,因为它能逼着你把“感觉”变成“假设”,再用证据去证实或排除。排查 Bug 不是靠灵光一现,而是靠证据链。
2. 前后端 Bug 的判断与实战
2.1 一眼定界:这个 Bug 到底归前端还是后端
项目里前后端联调,最常见的争执就是“这个 Bug 到底归谁”。其实定界的思路特别简单:打开浏览器开发者工具的 Network 面板,看请求到底发出去了没有,有没有响应,响应长什么样。
如果点击按钮后,Network 面板里根本没有任何请求发出,那大概率是前端问题,要么按钮没绑定事件,要么路由跳转压根没触发。如果请求发出去了,后端也回了,但返回的 4xx/5xx,那要看状态码和响应体是谁产生的,通常就是后端的问题,前端要配合提供请求参数。如果接口返回 200,但页面上数据不显示、状态不更新,那问题又回到了前端,要么是渲染逻辑写错了,要么是状态管理里的数据没接上。
我还有一个经验:先确认“是不是所有用户都受影响”。如果只有某一个人报 Bug,先看他的账号、浏览器、网络环境,说不定是缓存问题。如果所有人都出问题,再去查服务端和发布记录。按这个顺序,通常能很快把问题圈定在一个范围内。
2.2 前端排查的高频坑与常用切入点
前端问题三个最常用的切入点:Console 面板的报错、Network 面板的请求记录、还有 Application/状态管理里的数据。九成问题都能靠这三个入口定位,剩下的三成是渲染和兼容性。
有一个典型的例子,是用过的三维设计软件里“材料视图刷新异常”。某次切换材质库之后,视图里的旧材质颜色一直不消失,只有点击其他对象再切回来才刷新。这种 Bug 和接口没关系,是客户端渲染层的状态没有及时失效,类似前端常见的“组件缓存了旧数据没清掉”的问题。在没有源码的情况下,我的排查思路是:先尝试重置视图状态、清缓存,再看是不是显卡驱动兼容性问题,因为很多“显示不对”的 Bug 其实是 GPU 加速和渲染管线不兼容导致的。
前端最容易踩的几个坑,我列一下:一是浏览器缓存,前端发布后用户还开着旧页面,报一堆根本不存在的问题,所以遇到“用户说页面不对”先让他强制刷新;二是跨域,请求从页面发出去了,但浏览器因为 CORS 拦截了响应,在 Network 里能看到请求发出去,拿到不到数据,容易让人误判成后端问题;三是字段类型不一致,这个在前后端对接时特别常见,前端拿字符串“123”传给后端,后端用 Integer 接收,解析失败;四是第三方库版本更新后 API 变了,项目里某个组件突然开始报错,先查是不是依赖升级导致的 Breaking Change。
2.3 后端排查的关键抓手与 422 通信故障实录
后端排查的核心抓手永远是日志。我见过太多服务“日志都舍不得打一行”的做法,出了问题只能靠重启。我自己写代码的习惯是:每个关键接口入参、出参、异常堆栈都要留痕迹,每一条日志尽量带上 traceId 或 requestId,这样排查时可以把一次请求的全链路拼起来。
后端遇到“422 通信故障”,很多人会懵,因为这个状态码比 400 少见一点。422 是 Unprocessable Entity,意思是请求格式正确,但语义上没法处理,最常见的就是字段校验失败。我之前处理过一个案例:小程序端提交表单,数据看起来完全正常,但接口一直回 422。前端的同事把 Payload 截图发过来,我一眼看到问题:一个日期字段传的是“2024-06-10 14:30:00”,后端的 DTO 里定义的是 LocalDate,字符串转不了;另一个枚举字段传的是中文名称,后端期待的是整型数字。
这类问题的排查路径非常固定:打开 Network 面板,看请求的 Payload 长什么样,再对照后端的接口文档和数据校验规则,逐字段比对。404 和 405 是地址或方法不对,400 是请求格式不对,422 是“收到了但校验不过”。把这几类状态码的语义搞清楚,前后端沟通就能省掉一半扯皮。
2.4 构建脚本报错也有“潜台词”:semantic analysis 异常排查
有一种报错特别容易被当成玄学:bug! exception in phase 'semantic analysis' in source unit '_buildscript_' u。这个其实是 Gradle 构建脚本在编译阶段挂了,在做“语义分析”的时候发现了错误。很多人看到“semantic analysis”就以为是运行环境出问题,跑去查 JVM、查依赖,方向完全跑偏。
这种报错的本质是构建脚本本身无法通过编译,常见原因有三类:Kotlin DSL 语法写错了、引用了不存在的扩展函数或者依赖、buildSrc 或 buildscript 块的版本配置和主工程冲突。排查步骤很简单:先把堆栈拉到最顶部,看它定位到脚本文件的哪一行;再检查 Gradle Wrapper 的版本和 buildSrc 里配置的版本是否一致;如果还查不出来,把复杂脚本块注释掉,做最小化编译验证,用二分法缩小范围;最后清理一下.gradle缓存,排除缓存损坏的影响。
这类报错给我最大的教训是:看到报错里的“phase”关键字,先判断它是编译期还是运行期。编译期的错误,永远不要用“重启大法”去解决,重启一万次也不会有结果。
3. 网络与连接类故障排查实录
3.1 IP 冲突排查:从“网络很卡”到抓到肇事者
办公室里经常有人喊“网络卡”,一查发现是 IP 冲突。这个问题的经典现象是:终端频繁掉线,Ping 网关忽通忽断,过一会儿又自动恢复。我处理过的一台电脑就是这个症状,用户说“重启之后好一会儿,然后又开始卡”。
排查 IP 冲突最直接的办法是看 ARP 表。Windows 上用arp -a,Linux 上用ip neigh,如果看到同一个 IP 对应了两个不同的 MAC 地址,那就基本实锤了。我当时在 Windows 上执行arp -a,192.168.1.88 这个地址确实有两个 MAC 在来回横跳,一台是打印机,一台是电脑。打印机配了 DHCP 保留地址,电脑有人手工配了静态 IP,正好撞上了。
处理方式很简单:把电脑改成 DHCP 自动获取,或者把地址改成另一段没人用的 IP,再在交换机上看端口和 MAC。彻底一点的预防办法,是在网络设备上开启 DHCP Snooping 和动态 ARP 检测,绑定合法 DHCP 服务器,过滤非法 ARP 报文。不过大多数中小办公网络没那么严格,平时把“静态 IP 台账”整理好,避免随手乱配,就够用了。
排查网络问题时有个小技巧:先清理本地 ARP 缓存再测试。Windows 上用arp -d *,Linux 上用ip neigh flush all。清完缓存后立刻连续 Ping,观察 MAC 变化,能更快抓到肇事者。
3.2 连接超时与“模型请求失败”类问题的共性规律
“连接超时”这四个字听起来很具体,实际上覆盖的范围特别大。像 SecoClient 这类安全终端接入时报连接超时,我能想到的原因就有:目标地址和端口不通、服务端进程没起来、账号策略锁定、本地到服务端的路由有问题、证书过期导致 TLS 握手失败。所以我的习惯是先做排除:先用telnet ip port或者nc -vz ip port测端口通不通,通了再看上层;再在服务器上执行netstat -tulnp或ss -tulnp,确认服务进程真的在监听;接着检查本机的路由表,看是不是流量根本没走到对端;最后才看客户端软件本身的问题,比如版本、证书、配置项。
这个思路放到“模型请求失败”上也成立。调用外部模型服务报错,第一反应不应该是怀疑模型本身,而是看它返回的错误上下文。现在的客户端工具大多提供了“展开错误信息”这类交互,点开之后能看到更详细的状态码和阶段信息:是鉴权失败、配额超限、网络超时,还是参数非法。我之前排查过一个案例,调用方只看了第一行“请求失败”,怎么试都不行,后来展开完整信息,发现是账户余额不足,充完值立刻就好了。
所以在处理任何“连接超时”“请求失败”类问题时,我的原则是:先看完整报错,再测连通性,最后才怀疑服务端代码。顺序一旦搞反,就会陷入“重启、重试、再重启”的死循环。
4. 开发环境与系统层的 Bug 记录
4.1 装 Docker Desktop 的高频报错:虚拟化、WSL2 与常见坑
Windows 上装 Docker Desktop,报错最常见的就是虚拟化和 WSL2 相关。装完之后一启动,弹窗提示“Docker Desktop requires a newer WSL kernel version”,或者“Please enable virtualization in BIOS”。
先说前置条件。Windows 10/11 必须是 64 位系统,BIOS 里要把虚拟化(Intel VT-x / AMD-V)打开,Windows 功能里需要启用“适用于 Linux 的 Windows 子系统”和“虚拟机平台”。这两项启用之后必须重启,重启完再跑一遍wsl --status,确认默认版本是 2。很多人的报错都出在“默认版本还是 1”上面,执行wsl --set-default-version 2就能解决。
还有一类报错是“An unexpected error occurred”,这种情况十有八九和系统里其他虚拟化软件冲突。比如机器上装过 VirtualBox、VMware 之类的,或者 Hyper-V 和内核隔离状态不对,都会让 Docker Desktop 起不来。处理办法是先检查 Windows 功能里的 Hyper-V 是否启用,然后看“内核隔离”是否正常。如果把 Docker Desktop 从 WSL2 后端切到 Hyper-V 后端,报错内容会不一样,但本质差不多,都是虚拟化层没准备好。
另外一个高频报错是“Docker Desktop is unable to detect a Hypervisor”. 这种情况通常是因为 Windows 启动时进入了“内核隔离”被禁用或虚拟机监控程序没跑。检查systeminfo输出里最后一段,明确写着“Hyper-V 要求”是否都是“是”。如果这里显示“虚拟机监控程序已启动”,那就说明虚拟化层是好的,问题大概率出在 Docker Desktop 的安装配置上。这时候我一般会先去“控制面板-程序-启用或关闭 Windows 功能”,把“虚拟机平台”和“Hyper-V”勾选状态确认一遍,再重装 Docker Desktop。
4.2 Ubuntu 24.04 中文残留 Bug 与语言环境清理
升级到 Ubuntu 24.04 之后,有的朋友会发现系统菜单变成中英混杂的“阴阳脸”,有些应用界面还残留着旧版本的中文翻译,甚至个别对话框显示英文。这个严格意义上不算运行逻辑 Bug,而是语言环境和缓存的兼容性问题。
排查思路分三步。先看当前 locale:执行locale,看LANG是否已经是zh_CN.UTF-8;如果不对,检查/etc/default/locale里是不是写成了英文或者其他值。再看语言包有没有装全,Ubuntu 桌面版需要在“语言支持”里确认“简体中文”被勾选,命令行则检查language-pack-zh-hans是否安装。最后清理用户级缓存。升级后旧的 GNOME Shell 扩展、图标缓存、字体缓存还停留在老状态,注销再登录往往能解决大部分问题。
如果注销之后还有残留,那就需要手动清缓存。执行sudo dpkg-reconfigure locales,生成 zh_CN.UTF-8 编码,然后sudo update-locale LANG=zh_CN.UTF-8,再删除~/.cache下的 GNOME 和 fontconfig 缓存,重启系统。大部分情况下到这里就恢复正常了。如果还有个别应用显示英文,那就是应用自身没附带中文语言包,和系统无关。
4.3 winsxs 目录问题:Windows 组件存储的“怪病”
Windows 的C:\Windows\WinSxS是一个让很多人又爱又恨的目录。网上最常见的教程是“删除 winsxs 释放 C 盘空间”,但我必须说一句:千万别手动删这个目录。WinSxS 是 Windows 组件存储(Component Store),里面的文件大量使用硬链接被系统引用,手动删除会直接破坏系统更新和功能开关,严重的会导致系统无法启动。
WinSxS 目录看起来很大,是因为它里存着多个版本的系统组件,方便系统更新时回滚。但“看起来占空间”不等于“可以删”。微软自己的清理工具才能正确处理硬链接引用。
如果 C 盘空间确实被 WinSxS 拖累,正确做法是用 DISM。先执行DISM /Online /Cleanup-Image /AnalyzeComponentStore,它会告诉你组件存储里有多少是可以真正清理的,很多情况下你会发现“实际可回收”和“显示的大小”相差很大。之后执行DISM /Online /Cleanup-Image /StartComponentCleanup,这个命令会清理过期版本的组件。清理完再配合系统的“磁盘清理”工具,勾选“Windows 更新清理”,空间能释放不少。
WinSxS 还有一种问题是组件存储损坏,症状是系统更新失败、新功能安装不上。这种时候跑DISM /Online /Cleanup-Image /RestoreHealth,再用sfc /scannow修复系统文件。修复过程可能比较慢,但比重装系统成本低得多。
5. 资源与性能类问题的彻底排查
5.1 电脑卡顿怎么彻底排查
“电脑卡顿”是一个被说滥了但永远有人问的问题。我的排查思路不是看某一个指标,而是按 CPU、内存、磁盘、网络四个方向逐层排除。Windows 上按 Ctrl+Shift+Esc 打开任务管理器,先按 CPU 占用排序,再看内存占用,重点看磁盘那一栏是不是经常顶着 100%。很多卡顿的重灾区其实在磁盘:Windows Search 索引、Defender 实时扫描、磁盘碎片整理,这三个服务同时跑起来,机械硬盘直接变成“假死状态”。
磁盘层面还要关注“活动时间”而不是只看“占用率”。如果活动时间一直 100%,但读写速度很低,很可能是磁盘本身有坏道,或者 SATA 线松了。再用资源监视器看哪个进程在持续读盘。Linux 上排查卡顿,我会执行top看整体负载,vmstat 1看 r 和 b 列,r 持续大于 CPU 核数说明 CPU 排队严重,b 高说明磁盘 IO 排队。再用iostat -dxk 1看每块盘的%util和await,await 特别高的时候基本可以断定是磁盘拖后腿。
内存不足的表现也有迷惑性。Windows 上任务管理器显示“内存占用 90%”,不代表现在就卡,要看“已提交”和“工作集”。如果已提交内存长期大于物理内存加页面文件的总和,系统就是在硬撑着交换,卡顿就来了。定位内存泄漏,可以用 Process Explorer 看工作集和私有字节的差值,持续增长的进程往往就是嫌疑对象。
5.2 Codex 磁盘 Bug 与“空间莫名被吃”的问题定位
现在很多开发工具和 AI 编程助手都会在本地写日志和缓存,写多了就开始吃磁盘。比如 Codex CLI 这类工具,如果日志没有轮转策略,跑上几个月就能吃掉几个 GB。我遇到过一次开发机 C 盘空间掉得很快,排查后确认是~/.codex和~/.npm这两个目录在疯长。
这种“空间被悄悄吃光”的问题,定位方法其实很固定。Linux 上用du -sh /* 2>/dev/null逐层往下找,看哪个目录最大,然后du -sh ~/.cache/* | sort -hr | head -10锁到具体文件。还有一类隐蔽问题:某个进程已经删除了日志文件,但句柄还握着,磁盘空间被占用了却找不到文件。这时候要用lsof | grep deleted或者lsof +L1,把持有已删除文件句柄的进程找出来,重启进程或者让它释放句柄,空间立刻回来。
Windows 上排查空间被吃,最常用的工具是 WizTree 这类按 MFT 直接读目录树的软件,比资源管理器快得多,一眼就能看出哪个辣鸡目录最占地方。处理手段无非三种:清理缓存、配置日志轮转、把缓存目录改到别的分区。很多时候不用“根治”,只要设置一个定期清理任务,就能把问题控制在可接受范围内。这也是排查或者说治理的心得:有些工具型 Bug,管住它比修好它的性价比高得多。
6. Linux 系统排查指令大全与工具箱
6.1 我的收藏级排查命令清单
排查 Linux 系统问题,命令不在多,在精。我把自己实际用过、真正解决问题的命令整理了一张表,按场景分类如下:
| 排查方向 | 常用命令 | 典型使用场景 |
|---|---|---|
| 系统整体负载 | uptime、top、htop | 看 1/5/15 分钟负载,判断系统是否过载 |
| CPU 深入 | mpstat -P ALL 1、pidstat -u 1 | 看每个核心的使用率,定位哪个进程吃 CPU |
| 内存 | free -h、vmstat 1、cat /proc/meminfo | 看物理内存、交换分区、缓存的分配情况 |
| 磁盘空间 | df -h、du -sh *、find / -size +1G | 找大文件、确认分区使用率 |
| 磁盘 IO | iostat -dxk 1、iotop | 查%util、await,定位 IO 瓶颈 |
| 网络连接 | ss -tulnp、netstat -ano、lsof -i:8080 | 看端口监听、连接状态、谁占用端口 |
| 网络连通性 | ping、mtr、traceroute、curl -v | 测延迟、丢包、链路质量 |
| 抓包分析 | tcpdump、tshark | 定位协议层的异常,比如 TCP 重传、RST |
| 日志排查 | journalctl -u service --since "1 hour ago"、`grep -E "ERROR | Exception"` |
| 内核信息 | dmesg -T | 看内核是否报 OOM、硬件错误、磁盘 IO 错误 |
| 进程追踪 | strace -p PID | 看进程在调用什么系统调用、卡在哪 |
| 性能采样 | perf top、perf record、pidstat | 做热点分析,找函数级性能瓶颈 |
这里我想特别强调lsof这个命令。项目里排查“端口被占用”“文件被谁打开”“进程为什么还占着磁盘”,全靠它。比如lsof -i:8080能立刻告诉你 8080 端口被哪个进程占了;lsof +L1能找出那些“删了还在占用磁盘空间”的文件。这两条命令绝对值得刻进肌肉记忆。
strace适合另一种场景:程序好像没反应,但不知道卡在哪。附加到进程上看它正在读什么文件、连什么网络、等什么锁,很多“假死”问题一眼就能看出来。不过不要在生产环境长时间 strace,会有性能影响,观测一两秒拿到关键信息就够了。
6.2 排查中的记录习惯与日志定位技巧
命令再熟,没有好的记录习惯,排查效率依然上不去。我在排查 Bug 时养成了一个“时间线记录法”:把从发现问题开始,每做一步验证、看到什么现象、改变了什么配置,全部按时间点记录下来。比如“10:02 重启了 nginx,10:05 接口恢复,10:12 再次超时”,有了时间线才能看出规律,也方便把这些记录原样贴给同事一起判断。
日志定位也有技巧。journalctl --since和--until能按时间精确切出问题窗口,比翻整个日志文件高效得多。排查关键词时用grep -E "ERROR|Exception|Caused by"一把梭,先找到异常堆栈的起点,再往上翻两三行,通常就能看到上下文。tail -f适合实时盯日志,但在高并发日志量很大的服务上不要长时间开着,可以用tail -n 500先看文件尾部,再按关键字过滤。
最后一条:不要一上来就重启服务。重启相当于把犯罪现场抹掉了。哪怕决定重启,也要先把当前状态记录下来:netstat -tulnp、top、free -h、df -h、dmesg | tail -50,这五条命令把网络、进程、内存、磁盘、内核信息全抓到,再重启也不迟。
7. 常见问题速查与实战心得
7.1 常见问题速查表
把这些年常见的几类问题和对应解法整理成一张速查表,排查的时候可以先对着表看一遍:
| 症状 | 可能原因 | 最快验证手段 | 参考解法 |
|---|---|---|---|
| 接口报 422 | 前端提交的数据类型/格式与后端 DTO 校验不匹配 | 打开 Network 面板查看请求 Payload | 逐字段对照接口文档,修正类型和格式 |
| 客户端连接超时 | 端口不通、进程未监听、账号策略异常 | telnet ip port、ss -tulnp | 按网络层到应用层的顺序逐项排除 |
| 网络“卡”且时断时续 | IP 冲突、ARP 表异常 | arp -a或ip neigh,观察同一 IP 是否对应多个 MAC | 调整 IP 地址或做 DHCP 保留/MAC 绑定 |
| Docker Desktop 无法启动 | WSL2 未启用、内核过旧、虚拟化冲突 | wsl --status、systeminfo | wsl --update、检查 Hyper-V 和内核隔离 |
| Ubuntu 界面中英混杂 | language-pack 缺失、locale 未生效 | 执行locale检查 LANG | 安装 zh-hans 语言包并update-locale |
| C 盘空间不断减少 | 日志无轮转、缓存增长、句柄未释放 | du逐层定位大目录、lsof +L1 | 清理缓存、配置轮转、重启持有句柄的进程 |
| 构建脚本报 semantic analysis 错误 | 构建脚本语法错误、依赖版本冲突 | 查看堆栈首行定位脚本行 | 修正 Kotlin DSL 脚本、对齐 Gradle 版本 |
7.2 几条不写进文档的实战心得
第一,给 Bug 写日记,比写报告有用。报告是给别人看的,日记是给自己攒经验的。每次排查完整理成“现象/根因/解法”三条,几个月之后你就会拥有一本“症状字典”,遇到新问题直接翻以前记过的,能省下大量重复排查时间。
第二,复现成功,就等于修好了一半。很多难缠的 Bug 之所以难,难就难在它不听话。一旦你能稳定复现,就可以放心地做二分法、加日志、改代码验证,效率是蒙着头猜的十倍。所以拿到问题别先嫌弃它诡异,先想方设法把它“驯服”。
第三,别在半夜用排除法。遇到过线上告警,有人从晚上十点开始一项项排查到凌晨两点,越查越困,越困越乱,最后按错配置,把服务彻底搞挂。正确的做法是先恢复业务,比如切备份节点、回滚版本、临时降级,把用户影响先降到最低,等精神好了再慢慢查根因。排查这事儿,冲动是魔鬼。
第四,工具要会用,但不要神化。抓包工具很强大,但不能替代对 HTTP 状态码、TCP 握手、系统和日志的基本理解。命令只是放大器,真正的排查能力来自对“业务链路”的完整认知。知道一个请求从浏览器到前端代码、再到网关、再到后端服务、最后到数据库的完整路径,很多问题根本不需要工具,推理就能看出来。
这几年排查 Bug,我最大的感受是:这项工作和破案很像,证据链比灵光一现可靠得多。再难的问题,只要一五一十地记录现场、复现路径、缩小范围、验证假设,最后总能找到落脚点。修完一个难缠的问题之后,花十分钟写进日记里,下一次再碰到类似症状,你会感谢当时的自己。