接到告警说服务器负载高,登录上去先跑哪个命令?很多人的第一反应是top,看一眼 us 高不高、wa 高不高,然后……就没有然后了。真正的问题是:如果 us 高,下一步该看什么?如果 wa 高,你怎么知道是哪个进程在折磨磁盘?如果内存明明还有几个 G 的空闲,业务却像被掏空了一样卡顿,这又是怎么回事?
作为一个常年跟 Linux 服务器打交道的运维,我太清楚这种“命令背了不少、一上机器就抓瞎”的状态了。原因很简单:排查性能问题,缺的不是某个神奇命令,而是一条完整的分析链路。CPU、内存、带宽这些指标不是孤立数据,它们是同一台机器上的共享资源,任何一个出现瓶颈,都会让业务表现出现类似的“卡、慢、超时”,但方向选错了,后面全白做。
这篇文章不打算写成命令手册的搬运工,我按实际排查的顺序,把 CPU、内存、带宽这几个维度的核心命令、每个命令输出里最值得盯的指标、以及命令背后的判断逻辑拆开讲清楚。内容会更适合那些已经能熟练操作 Linux、但遇到线上故障时总感觉缺少一套完整思路的人。
1. 排查前的第一步:先分清方向,而不是先跑命令
很多新手(甚至不少老手)犯的第一个错误,是拿到服务器就迫不及待地敲命令。这就像病人还没挂号,你就开始给他开药。真正高效的排查,第一步不是跑命令,而是先做信息收集:这个告警是怎么来的?是 CPU 使用率超过 90% 的主动告警,还是业务方反馈接口超时的被动告警?是同机房所有机器一起报警,还是只有这一台?
这两类来源,决定了完全不同的排查起点。如果是监控系统主动告警,那么问题大概率就出在告警指标本身,顺着指标往下查就行。但如果是业务方反馈慢,那就要警惕了:用户感觉到的慢,不一定是资源不足,还可能是应用代码里有慢查询、有锁竞争、有垃圾回收停顿,甚至可能是某个上游接口把调用线程池占满了。
1.1 先看 Load Average,但这玩意容易骗人
uptime命令给出的 load average,是我建议的默认起点。它包含三个数字,分别是过去 1 分钟、5 分钟、15 分钟的平均负载。很多文章告诉你“负载不能超过 CPU 核数”,这话对了一半,因为它没有区分负载的构成。
负载的本质是“处于可运行状态和不可中断睡眠状态的进程数”的统计平均值。可运行状态是指正在用 CPU 或排队等 CPU 的进程;不可中断睡眠状态通常是在等磁盘 I/O 的进程。也就是说,如果你看到负载很高,不能直接断定是 CPU 不够,也可能是磁盘 I/O 阻塞了太多进程。
有一个比较实用的判断方法:把 load average 和 CPU 核数对比,同时叠加观察趋势。如果 1 分钟负载远高于 15 分钟负载,说明是近期突然飙高,大概率是业务流量突增或某种异常任务。如果三个数字都很高且一直居高不下,那就是持续性的资源瓶颈。但这只是方向,具体是 CPU 还是 I/O,还需要下一步拆解。
1.2 三层过滤:从系统全局到进程,再到线程
我自己的排查习惯,是遵循一个“系统级 → 进程级 → 线程级”的三层过滤思路。系统级看整体资源态势,进程级锁定“谁在制造问题”,线程级才能定位到具体的代码执行点。比如 CPU 高,系统级用mpstat看是不是某颗 CPU 被打满,进程级用top排序找出那个进程,线程级用top -H找到具体线程号,再结合 Java 的jstack或 C/C++ 的调试器去看代码栈。
这套思路同样适用于内存和带宽排查。内存系统级用free看剩余量和 cache,进程级用ps按内存排序,再深入就要看进程内部的内存映射或者堆内存使用率。带宽也是,系统级用iftop或nload看总流量,进程级用nethogs(如果没有装上,可以结合ss看连接和进程),要再往深走就是抓包看具体连接的流量特征。
这个三层过滤的意义在于,它让你每一步行动都有依据,而不是被一堆命令的输出带着跑。
2. CPU 排查:top 只是入口,别在入口处迷路
top是 CPU 排查的经典入口,但它的输出信息密度太高,新手很容易被各种行和列带偏。我建议先只盯前几行里的关键指标,确认方向之后再往下挖。
2.1 top 第一行和第二行的正确读法
先说第一行 load average,前面已经聊过了,它告诉你的是整体负载趋势,而不是当前 CPU 用量。第二行是进程和 CPU 状态统计,真正有价值的是这行里的%Cpu(s)前面的状态拆解行,比如 us、sy、ni、id、wa、hi、si、st。
这里重点看四个值:
- us:用户态 CPU 占比。如果 us 持续超过 80%,说明是应用本身在大量消耗 CPU,这时要优先怀疑代码逻辑、死循环、复杂计算或者 GC 频繁。
- sy:内核态 CPU 占比。sy 超过 20% 就需要警惕,常见原因是系统调用过多、上下文切换频繁,比如高并发的短连接请求会大量触发系统调用和软中断。
- wa:等待 I/O 的 CPU 占比。如果 wa 高但 us 不高,说明 CPU 大部分时间在等磁盘,问题方向应该在存储而不是计算。
- st:被虚拟化环境偷走的 CPU 占比,云服务器上要额外注意,如果 st 长期偏高,那大概率是宿主机上的邻居在争抢资源,这种时候单纯优化应用已经没什么用了。
2.2 从进程定位到线程:换一种看待 top 的方式
找到吃 CPU 的进程后,下一步是确定是哪个线程在作怪。这里用的还是top,但要加上-H参数,并且把显示方式切到按 CPU 排序。在交互界面里按P键,或者直接执行top -Hp 进程PID,就能看到该进程下所有线程的 CPU 占用情况。
拿到占用最高的线程 ID 后,这个数字是十进制的,而在 Java 线程转储文件(jstack 输出)中线程号通常是十六进制。这就要求你做一个进制转换:printf "%x\n" 线程ID。转换出来的十六进制值,去 jstack 输出里搜,就能精准定位到出问题的代码栈。
这个方法同样适用于 Native 应用。对于 C/C++ 程序,拿到高 CPU 线程号后,可以附加 gdb 或者使用perf top -p 进程PID -t 线程ID来看热点。很多人会卡在“知道进程高,但不知道哪行代码高”这一步,其实只是缺了进制转换这个细节。
2.3 别忽略短时间内尖刺:vmstat 配合使用
top看的是瞬时状态,如果问题不是持续性的,而是每隔几十秒才出现一次,你在top里可能根本看不到什么。这时要引入vmstat,它能在后台定期采样,记录系统状态的连续变化。
vmstat 1 10的意思是一秒采样一次,一共采样 10 次。重点看第三行的 r(运行队列)和第四行的 us、sy、wa 列。采样多次后,如果发现 r 值经常超过 CPU 核数,那说明 CPU 资源已经处于饱和排队状态。如果 wa 列时不时冲到很高,说明 I/O 尖刺是间歇性的,这种场景下,top的瞬时快照当然捕捉不到。
我之前遇到过一台机器,业务方反馈每隔 5 分钟卡一下,每次卡 30 秒左右。直接top看 CPU 一切正常,后来用vmstat 1连续记录,发现 wa 列周期性飙到 90% 以上,顺着往下查才知道是 cron 定时任务在每 5 分钟触发一次全量日志压缩,把磁盘 I/O 打满了。
2.4 核心场景拆解:us 高、sy 高、wa 高分别怎么查
CPU 排查容易卡住,很多时候是不清楚不同状态高代表什么方向。这里整理一个对照表,是我自己排查时习惯用来快速对方向的。
| 现象 | 初步判断 | 下一步操作 |
|---|---|---|
| us 高,用户态 CPU 持续饱和 | 应用代码消耗大 | 定位线程栈,检查是否有死循环、大计算、GC 或锁竞争 |
| sy 高,内核态 CPU 使用偏高 | 系统调用频繁、上下文切换多 | 用vmstat看 cs(上下文切换)列,必要时用perf分析内核热点 |
| wa 高,CPU 大量等待 I/O | 磁盘读写是瓶颈 | iostat -x 1看 %util 和 await,定位热盘和热点分区 |
| st 高,虚拟化 CPU 被抢占 | 宿主机资源争抢 | 换云厂商物理机或调整实例规格,这属于资源层问题 |
| hi/si 高,硬/软中断频繁 | 网络包或磁盘中断过密 | 结合cat /proc/interrupts看中断分布,可能网卡队列不均 |
这张表的价值在于帮你快速缩小范围,但别把它当绝对标准。比如 sy 高有时也伴随 us 高,这时优先看线程栈,因为大多数系统调用都是由用户态代码直接或间接触发的。
3. 内存排查:free 只是开胃菜,重点在于理解内存到底去哪了
内存问题比 CPU 问题更隐蔽,因为 Linux 的内存管理机制里有个容易让人误解的输出:明明程序很吃内存,但free一看还剩好几个 G,这就让人松懈了。实际上 Linux 把空闲内存拿去做 cache 是正常现象,关键要看的是“可回收”和“不可回收”的构成,以及具体进程的占用趋势。
3.1 读懂 free -h 的三行输出
free -h的输出分三行,可以用一两个词概括:物理内存总量、已用、空闲、shared、buff/cache、available。这里最容易混淆的是 used 这一列,它没有包括 buff/cache,而 buff/cache 里的绝大部分是可以随时释放的。真正需要关心的是 available,它才是估算“还能分配多少内存给新程序”的可靠指标。
如果你看到 available 很低,而 buff/cache 很高,先不要急着怀疑缓存进程。这时候可以查看哪些进程占用内存最多:ps aux --sort=-rss | head -n 20。按 RSS(常驻内存)排序,能快速列出物理内存消耗最大的进程。
但这里有个细节很多人会踩坑:RSS 会把多个进程共享的共享库计算多次,导致个别进程的 RSS 看似异常高。要更精确地评估单进程内存,建议去看/proc/PID/smaps或者用smem工具,它会在 RSS 基础上扣除共享库的重复计算,给出更接近实际的 PSS 值。
3.2 别小看了 Page Cache 的延迟问题
很多线上故障的根子,出在 Page Cache 上。Linux 为了提高文件读写性能,会把读写过的磁盘页缓存在内存里。正常情况下,当内存压力出现时,内核会通过后台回收线程释放一部分缓存,这个过程叫 kswapd 或直接回收。但在某些极端场景下,比如一次性大面积写入大文件、或者某个程序突然读取了大量数据,cache 会急速膨胀,短时间内把可用内存压没。
表现是什么?业务进程启动不了,提示 Out of Memory 错误,但是free一看 buff/cache 巨高。很多人这时候就慌了,想把 cache 手工清掉,执行echo 3 > /proc/sys/vm/drop_caches,然后就发现业务照样起不来——因为 cache 虽然释放了,但内存分配还要时间,而且有些页是脏页,必须先写回磁盘才能释放,这个动作会导致磁盘 I/O 突发,反而让系统更卡。
正确的处理方式,一是确认进程确实是因为内存不够起不来,二是调整 vm 层参数比如vm.zone_reclaim_mode、vm.min_free_kbytes等,或者通过 cgroup 限制其他进程的内存占用。手工 drop_caches 这个动作,我建议只在低峰期应急使用,不要当作常规操作。
3.3 内存泄漏定位的一种实用套路
内存泄漏的表现是随着时间推移,进程的 RSS 或堆内存持续增长,但重启后恢复。定位内存泄漏,最直接的方式是监控进程的内存趋势,而不是等到 OOM 杀进程之后才找根因。
可以用/usr/bin/time -v 命令来查看进程峰值的 max resident 值,但这只适用于短生命周期任务。对于长驻进程,配合top -p PID定期记录 RSS,或者借助监控系统画内存趋势图,观察是线性上升还是阶梯式上升。如果是 Java 或 Go 服务,还可以通过暴露的内存指标接口(比如 Prometheus 的 jvm_memory_used_bytes)来细分堆内、堆外、Metaspace 等区域。
定位到具体泄漏点时,Java 服务可以连续抓两份jmap -histo:live输出对比,看哪些类实力数量在暴涨;Native 进程可以用valgrind或 AddressSanitizer 重新编译运行。不过这些工具在线上环境往往不好直接启用,更常见的做法是先用pmap -x 进程PID看虚拟内存段分布,再结合代码审查定位。
3.4 堆外内存与堆内内存:Java 场景的一个特殊关注点
热词里出现了“jvm内存模型”和“堆外内存”,说明不少人在 Java 应用的内存排查上踩过坑。Java 进程的内存不只是-Xmx指定的堆内存,还包括线程栈、Metaspace、DirectBuffer(堆外内存)、JIT 编译产物等。经常出现的一种诡异现象是:堆内存使用率正常,但整个进程的 RSS 很高,甚至被内核 OOM。
这种场景下,要检查两个方向。一是 DirectBuffer,它通过ByteBuffer.allocateDirect分配,不受堆大小限制,却算在进程 RSS 里。二是 JNI 调用的 Native 库,比如常见的解压缩库、OpenSSL 等,可能在 C 层分配了大量内存。排查手段上,可以通过-XX:MaxDirectMemorySize限制 DirectBuffer 大小,用jcmd 进程PID GC.heap_info看 JVM 的角度统计,再配合pidstat -r或者查看/proc/PID/status里的VmRSS,对比 JVM 报告的内容和操作系统看到的内存,差额很可能就是堆外部分或 Native 内存。
排查思路可以按下面这个流程走:
- 用
ps aux或top确认进程 RSS 是不是真的异常。 - 用
jcmd或jstat确认堆内内存区域是否正常。 - 如果堆内正常,看 DirectBuffer 统计:
jcmd 进程PID VM.native_memory(需要 JVM 启动参数开启 NMT)。 - 对比
/proc/PID/status里的 VmRSS 和 JVM 统计,差额大的话,考虑 Native 库或线程栈消耗。
4. 带宽排查:不只盯着流量大小,更要看连接质量
说到带宽,很多人第一反应是看“流量满没满”。但实际上,网络性能问题大致可以分两种:一种确实是流量达到物理带宽上限,另一种是网络质量变差导致的重传、丢包、延迟增高。这两种问题的处理方法完全不同,而排查入口也不太一样。
4.1 先量化:当前机器流量到底有多大
最直观的工具是iftop,它会像top一样实时刷新网络连接流量,按流量大小排序。如果一时没有安装,用nload也可以,它能画两个大字符图形,分别展示进方向和出方向的速率。
不过我想特别提醒一点:如果是云服务器,iftop看到的是实例内部的虚拟网卡流量,不一定等于云厂商计费的“带宽”。比如公网流量会不会经过 NAT 网络、内网流量是否被限速,这些在虚拟化环境下视图可能有差异。真有疑问时,建议先到云控制台看监控曲线,那个数据往往更接近实际计费出口。
单纯看流量大小是不够的,还要对数量级有概念。假设一台 2 核 4G 的机器,公网带宽规格是 5Mbps,那它的上限就是每秒 640KB 左右。如果iftop显示瞬间流量到了 3Mbps,它就明显是热点问题。但要是机器规格是 100Mbps,你却只看到 10Mbps 流量在跑,这时出现卡顿,优先去查延迟和丢包,而不是流量。
4.2 延迟与丢包:用 ping 粗略看,用 MTR 精细看
排查网络质量,最粗糙的办法是ping -c 100 目标IP,看丢包率。如果丢包率持续超过 1%,那传输层就很容易出现重传,TCP 吞吐量会断崖式下滑。但ping只是能测通,它直接测的是 ICMP 协议,实际应用走的是 TCP 或 UDP,表现并不完全一致。更实用的工具是mtr,它像是traceroute和ping的结合体,能展示从本机到目标地址每一跳的丢包和延迟情况。
mtr -r -c 100 目标IP会给出每一跳的统计。这里有个观察技巧:如果丢包只出现在最后一跳(目标服务器那一跳),而中间路由器都正常,那问题大概率在目标服务器的自身处理能力,比如防火墙规则导致的丢包、目标服务器的 TCP 接收队列满等。如果丢包出现在中间某两个节点之间,那就要考虑网络链路本身的问题。
4.3 TCP 重传检查:一个被很多人忽略的重要指标
TCP 重传是网络质量问题的直接反映,但在多数操作系统的默认监控里却容易被忽略。快速检查方式是ss -s,它会输出 TCP 连接的统计信息,里面包含当前的重传率估算。但更准确的是netstat -s,它统计了从启动到当前时刻的累计重传次数。
如果累计重传次数很高,最好是先确认是不是某个具体的连接在频繁重传,而其他连接都正常。ss -i可以查看每个 socket 的详细信息,包含发送队列、接收队列、拥塞窗口等。如果要实时看重传事件的现场,可以用tcpdump抓包,抓取特定端口的流量,检查是否有大量重复的 ACK 或超时重传。
重传的根因通常分两种:一种是网络链路丢包,比如运营商线路不稳定、防火墙策略丢包;另一种是缓冲区不足导致的丢包,比如接收端应用程序处理不过来,socket 接收缓冲区被填满,内核只能丢包。这两种情况的处理方向南辕北辙:前者需要找网络服务商或者优化路由,后者需要优化应用处理性能,甚至调整sysctl参数(如net.core.rmem_max、net.ipv4.tcp_rmem)。
4.4 连接数与连接状态:带宽限制之外的另一种“带宽”
在带宽排查的链路中,连接数这个维度经常被忽视。一台机器即使总带宽没有打满,但 TIME_WAIT 或 SYN 队列堆积,同样会让新连接进不来、业务仿佛被网络卡死了。
ss -s能快速看到不同状态连接的数量,ss -ant | awk '{print $1}' | sort | uniq -c这种命令则能按 TCP 状态做个快速分组。如果 TIME_WAIT 数量庞大,通常说明大量短连接没有被有效复用,后续可以考虑开启tcp_tw_reuse或者优化应用的长连接策略。如果 SYN_RECV 状态的连接一直很多,说明半连接队列满了或 handshake 没完成,配合查看/proc/net/netstat里的ListenOverflows,基本就能判断是不是 SYN 泛洪被排队到了。
我自己排查过一个典型的连接数问题:一台机器的带宽并没有跑满,但接口频繁出现超时。用ss -s一看,TIME_WAIT 连接数超过两万。进一步抓包确认,是业务请求里频繁创建了新的 TCP 短连接给 Redis,而 Redis 本身也有连接数限制。最终方案改成了连接池复用,问题立刻缓解。网络问题有时并不在链路上,而在连接资源的管理上。
5. 综合实战案例:从 top 到定位根因的完整排查链路
前面把 CPU、内存、带宽分别拆开了讲,但在真实场景里,它们往往是搅在一起的。我来分享一个比较有代表性的案例,把前面说的思路串成一条完整链路。
5.1 现象:业务接口平均耗时从 50ms 涨到 800ms
某天上午,一个 Web 服务出现严重的响应变慢。我先是从监控上看到机器节点的 CPU 使用率没有明显飙升,内存也足够,但接口耗时呈线性爬升趋势。直觉告诉我,问题可能不在计算资源上,而是网络或锁之类的点,需要登录服务器进一步确认。
第一步,登录后先跑uptime看负载,负载 4.2,但机器是 8 核的,这个数值并不算高。接着跑mpstat -P ALL 1看单核分布,发现各核心使用率很均匀,都不超过 40%。这基本排除了 CPU 瓶颈。
第二步,跑free -h,内存 available 还有 6G 多,buff/cache 也不算反常,内存方向暂时排除。
第三步,顺理成章怀疑网络层。使用ss -ant看到大量连接处于 ESTABLISHED 状态,且重传率有点高。进一步iftop看流量,发现出方向流量只有 2Mbps 左右,远没有达到带宽上限。这就矛盾了——流量不大,重传却不低。
5.2 深入:从重传找到真正的黑洞
既然有重传,我决定用tcpdump抓包定位是哪些连接在重传。tcpdump -i eth0 tcp port 8080 -w /tmp/tcp.cap抓了大约 30 秒的包,然后用 Wireshark 打开,通过统计菜单里的 TCP 分析,看到大量重复 ACK 都指向同一个目标段 IP。顺着排查这个 IP 段的通信质量,发现是跨机房的专线出现了间歇性丢包,丢包率 3% 到 5%。
这里有一个关键点:TCP 丢包 3% 对用户感知而言可能已经非常明显了。因为它会导致拥塞窗口收缩、触发快速重传或超时重传,应用层接口耗时就可能十倍甚至百倍增长。而流量本身没有打满,是因为拥塞控制机制在丢包时主动降低了发送速度,这是一个自我保护的假象。
最终处理是和网络团队确认,专线在那一时间段进行了路由割接,割接过程中出现了不稳定。等网络操作完成、路由收敛稳定后,重传率自然降下来,业务耗时也恢复了。
5.3 复盘:为什么 CPU 和内存都没问题,却如此卡顿
复盘这个案例,我最想强调的其实是排查顺序和思路的价值。如果当时我看到 CPU 不高、内存够用,就得出“服务器没问题”的结论,这个方向就完全错了。资源充裕与业务稳定之间,不是简单等式。网络链路上的问题,同样可以表现为外层业务的异常。
另一个收获是:重传率是一个比流量大小更有意义的信号。流量不高不代表网络就健康,它可能只是演员在拥塞控制的操控下放慢了脚步。遇到类似“接口变慢但资源不紧张”的故障,建议优先检查 TCP 重传和延迟抖动。
做一次完整排查的动线如下:
- 面对异常,先跑
uptime和vmstat 1 5,快速确认系统整体是否健康。 - 再看 CPU 单核分布和内存可用量,排除计算与存储的显著饱和。
- 仍无头绪时,趁早进入网络层,先
ss -s看连接统计,再用iftop看实时流量,最后用tcpdump抓包确认是否为链路问题。
6. 长期监控与常用速查:把事后排查变成事前感知
上面讲的都是“已经出问题,你得赶紧查”的应急场景。但更成熟的做法,是让这些问题在还没有影响业务之前就被发现。这也是为什么我建议你在机器上提前布好监控,同时建立几个固定脚本,让你在需要时能一键收集关键指标。
6.1 轻量监控方案:不用重工具也能覆盖核心指标
并不是所有团队都有条件上完整的 Prometheus + Grafana,很多小团队可能只有一台测试机和一台生产机。这种情况下,我推荐用三个轻量手段搭起一个“极简监控网”。
第一,用crontab定期执行vmstat、free、ss -s的记录脚本,把输出追加到/var/log/perf/目录下的文件里,保留 30 天。一旦出问题,翻历史文件就能看到时间点的资源快照。脚本很简单,核心是加上date时间戳。
第二,用sar采集历史数据。安装sysstat后,sar -u可以看历史 CPU、sar -r看历史内存、sar -n DEV看历史网络流量。前提是sysstat的后台采集服务已经启动。这套工具的优点是采样频率比手动命令更密集,能让你判断问题是从什么时候开始的。
第三,业务访问日志里的耗时曲线,往往是最早的告警信号。如果你的网关或应用框架里有请求耗时日志,定期扫描 p95、p99 耗时,一旦这两个值超过设定阈值,就值得深入排查了。很多时候,服务器资源还完全正常时,业务耗时已经先一步开始涨。
6.2 一页纸速查:覆盖 CPU、内存、带宽的核心命令
最后,我把高频用到的命令整理成一个速查表,方便你贴在笔记里,或者在排查时直接翻开对照。
| 场景 | 命令 | 重点关注 |
|---|---|---|
| 总览负载 | uptime | load average 的 1/5/15 分钟值及趋势 |
| CPU 状态 | mpstat -P ALL 1 | us/sy/wa/st,尤其单核是否有热点 |
| 上下文切换 | vmstat 1 | r 和 cs 列,cs 过高查锁与短线程 |
| 定位线程 | top -Hp PID | 最高 CPU 的线程号(十进制) |
| Java 线程转储 | jstack PID | 匹配线程号的十六进制值 |
| 内存概览 | free -h | available 列,而不是 used 列 |
| 进程内存排序 | ps aux --sort=-rss | RSS 最高的进程 |
| 精确进程内存 | smem -k -s rss | PSS 值,扣共享内存后更合理 |
| 流量实时 | iftop/nload | 进/出方向速率,哪个连接占流量高 |
| 连接状态 | ss -ant | TIME_WAIT、SYN_RECV 数量 |
| TCP 统计 | netstat -s | 重传、乱序、丢包累计值 |
| 全路径网络质量 | mtr -r -c 100 IP | 丢包率出现在哪一跳 |
| 抓包分析 | tcpdump -i eth0 port 8080 -w /tmp/t.cap | 重复 ACK、重传包特征 |
7. 最后分享几个调试小技巧
排查做到最后,我发现很多经验不是从书里学来的,而是被线上事故教育出来的。说几个我自己的习惯,可能对你也有用。
第一,线上操作前先留证据。哪怕你只是跑一下top,最好也把输出存到文件里。很多问题带有瞬时性,等你分析完再回看,现场可能已经变了。存下来的快照能帮你回溯和复盘,也能在汇报故障时给团队提供依据。
第二,尽量别在业务高峰期执行会引发系统级阻塞的调试操作。比如strace -p PID这种动态追踪工具,它会让目标进程暂停在系统调用边界,甚至把整个进程卡死。如果非要做,先确认维护窗口,或者改用perf这类对被观测程序影响更小的工具,并且限制采样时间。
第三,定期给自己的服务器做“性能基线”记录。同一个接口在业务低峰期响应 30ms,高峰期响应 300ms,这些数字本身没有绝对意义,但如果你有历史基线,就能很快判断当前的 800ms 是不是异常偏离。很多问题都是相对变化,而不是绝对数值。
Linux 排查这条路没有终点,因为生产环境永远在变,旧的坑填完新的坑又会出现。但只要你掌握了“先定方向、再逐层拆解、最后精准定位”的思考方式,即便遇到没见过的诡异现象,也不会慌乱。希望这篇文章里那些从实战里摸出来的细节,能让你在下次面对报警时,少走几步弯路。