
目录一、排查框架接到告警后第一件事做什么1.1 黄金5分钟建立全局认知1.2 快速定位方向看vmstat决定下一步二、场景一CPU飙升100%2.1 现象2.2 排查流程2.3 CPU排查总结三、场景二内存泄漏排查3.1 现象3.2 排查流程3.3 内存泄漏排查总结四、场景三磁盘满了但找不到大文件4.1 现象4.2 排查流程4.3 磁盘排查总结五、综合排查速查表六、本篇小结动手练习七、下篇预告一、排查框架接到告警后第一件事做什么1.1 黄金5分钟建立全局认知半夜被报警叫醒你最不该做的就是随机敲命令乱试。没有明确方向的排查只会浪费宝贵的恢复时间。前5分钟只做一件事建立全局认知锁定问题范围。标准流程只有五条命令bash# 1. 系统整体负载1分钟/5分钟/15分钟平均负载 uptime # 2. 内存概况available是最关键的指标 free -h # 3. 磁盘空间满了什么都做不了 df -h # 4. 系统整体负载分解rCPUbI/Owa等待I/O vmstat 2 5 # 5. 最近的系统日志内核、服务、OOM等异常 journalctl -p err --since 30 min ago做完这五条回答自己三个问题负载高吗uptimevs CPU核心数负载是哪来的vmstat的r列还是b列高wa有多高最近有什么异常事件OOM Killer服务重启磁盘错误1.2 快速定位方向看vmstat决定下一步textvmstat 2 │ ├── r 列持续 CPU核心数 ──→ CPU瓶颈 │ ├── b 列持续 0 ──→ I/O瓶颈 │ ├── si/so 持续 0 ──→ 内存瓶颈正在换页 │ └── 三者都正常 ──→ 网络或应用层问题这4个判断足够覆盖90%的生产故障。方向错了后面的所有排查都是浪费时间。接下来我们按三种最经典的故障场景逐一展开完整的排查流程。二、场景一CPU飙升100%2.1 现象监控告警某台服务器的CPU使用率突然飙升到100%且vmstat确认r列远大于CPU核心数。2.2 排查流程第一步找出吃CPU的进程bashtop -c # 按 P 确保按CPU排序 # 记下排在最前面的PID和进程名假设PID为12345进程名是java某个Java应用。第二步细化到线程级别对于多线程应用Java、MySQL一个进程的CPU高通常是某几个线程导致的bash# 查看进程内每个线程的CPU使用率 top -H -p 12345 # 记下最高CPU的线程IDTID假设为 12389第三步将线程ID转十六进制bashprintf %x\n 12389 # 输出3065第四步查看该线程的调用栈bash# jstack是Java专用工具输出进程内所有线程的调用栈 # 用十六进制TID3065搜索对应的线程 jstack 12345 | grep -A 20 3065 # 如果是其他应用非Java用perf采样CPU调用栈 sudo perf top -p 12345输出会显示线程当前正在执行的函数名。从调用栈中的函数名可以判断频繁GC垃圾回收→ 内存不够检查堆大小或排查内存泄漏正则表达式匹配 → 可能是正则回溯问题或恶意输入业务代码的死循环 → 代码逻辑bug加密/压缩等计算密集函数 → 正常的计算任务考虑优化算法或限流2.3 CPU排查总结texttop → 找高CPU进程 top -H -p PID → 找高CPU线程多线程应用 jstack/perf top → 看调用栈找根因三种常见根因死循环业务代码bug频繁GC内存不足或内存泄漏导致正常计算密集加密/压缩/转码等考虑加CPU或限流三、场景二内存泄漏排查3.1 现象服务器内存使用率持续增长即使业务低谷期也不下降。重启后恢复正常但运行几天后又涨回去。这是典型的内存泄漏特征。3.2 排查流程第一步确认内存分布bashfree -h # available持续减少buff/cache没有增加 → 匿名页程序堆/栈在增长buff/cache是文件缓存涨了不意味着泄漏。如果used不断增加而buff/cache基本不变说明应用在持续申请匿名内存。第二步找出内存大户bashps aux --sort-%mem | head -10 # 或者用更精确的PSS统计 sudo smem -p -s pss | head -10假设PID为12345的进程内存占用不停增长。smem的PSSProportional Set Size比例共享大小比RSS更准确因为它把共享库的内存按比例分摊给了各个使用它的进程。第三步查看该进程的内存增长趋势bash# 每10秒打印一次内存使用持续观察 while true; do echo $(date %H:%M:%S) $(smem -p -c pid pss -P 12345 | tail -1) sleep 10 done如果PSS持续增长 → 确认泄漏存在于该进程中。第四步查看进程内存分配细节bashpmap -x 12345 | tail -1 # 或者 cat /proc/12345/status | grep -E VmRSS|VmSizepmap显示该进程的虚拟内存映射——每一段内存的起始地址、权限、大小和来源映射的是哪个文件还是匿名分配。如果某段匿名内存anon异常大比如占总内存的80%以上可以基本确认是程序内部在持续申请内存而不释放。第五步使用valgrind深入分析开发环境bash# Valgrind的memcheck工具会模拟执行程序追踪每一块内存的分配和释放 # 注意这会使程序运行速度减慢10-20倍只能在开发环境使用 valgrind --leak-checkfull --log-filevalgrind.log ./my_app cat valgrind.log | grep definitely lost输出会精确指出代码中哪个文件、哪一行分配的哪块内存没有被释放。这个信息交给开发人员可以精确定位泄漏点。3.3 内存泄漏排查总结textfree -h → 确认内存增长类型 ps/smem → 找到内存增长进程 pmap/proc/PID/status → 确认进程中哪部分内存异常匿名页还是共享内存 valgrind开发环境→ 定位到具体代码行常见根因应用代码bug忘记释放内存、循环中反复分配缓存未设上限进程内缓存如HashMap无限增长线程泄漏线程创建后未正确回收每个线程默认占用约8MB栈空间四、场景三磁盘满了但找不到大文件4.1 现象df -h报告磁盘使用率90%以上但用du -sh /*逐层排查所有目录加起来的大小远小于df显示的已用空间。为什么df和du结果对不上df是从文件系统元数据中直接读取的块使用量反映的是磁盘块分配情况du是遍历目录树把每个可见文件的大小累加起来如果有文件被删除了但进程还持有它的文件描述符du统计不到但df知道这些磁盘块没有被释放4.2 排查流程第一步确认df和du的差异bashdf -h / du -sh / 2/dev/null # 如果df显示40G已用du显示30G但加起来确实找不到后10G在哪这种悬殊差异差了几个GB而目录遍历完全找不到对应文件说明有被删除但仍在被进程持有的文件。第二步找出“已删除但仍被占用的文件”bashsudo lsof | grep deleted | awk {print $1, $2, $NF} | sort -u # 或者更精确地显示文件大小 sudo lsof L1L1是lsof的专用参数表示“列出所有链接计数小于1的文件”即被删除但进程仍打开着的文件。输出示例textCOMMAND PID USER FD TYPE DEVICE SIZE/OFF NLINK NODE NAME java 12345 app 12w REG 253,1 8589934592 0 56789 /var/log/app.log (deleted)这条输出显示进程javaPID 12345的文件描述符12w指向一个已被删除的文件/var/log/app.log它占用了8.5GB的磁盘空间。那个“(deleted)”标记就是罪魁祸首——文件已不在目录中但内核因为进程还打开着它不会释放它的磁盘块。第三步释放空间bash# 如果是日志文件直接清空 sudo truncate -s 0 /proc/12345/fd/12 # 或者让进程重新打开日志文件更优雅需要进程支持 kill -HUP 12345 # 发送SIGHUP许多守护进程会重新打开日志文件 # 如果不关心这个文件的内容直接杀掉进程 sudo kill 12345truncatevskilltruncate -s 0通过/proc/PID/fd/文件描述符来截断文件内容进程无感知不会中断服务。kill会终止进程如果这个进程是关键服务可能造成宕机。因此优先用truncate。4.3 磁盘排查总结textdf -h → 确认分区已用空间 du -sh /* → 找到空间占用大的目录 df和du结果悬殊 → 被删除文件仍被占用lsof L1 lsof L1 → 找到进程和文件描述符 truncate -s 0 /proc/PID/fd/FD → 释放空间常见根因日志轮替不当应用在持续写入logrotate脚本用rm删了文件但没有用kill -HUP通知应用重新打开日志句柄。文件虽删数据继续往内核的旧inode里写临时文件未清理应用创建的临时文件被删除但句柄未关闭大文件仍被进程持有有人rm了一个大文件但不知道有进程还在用它五、综合排查速查表现象第一步命令第二步命令关键判断负载高uptimevmstat 2r高→第三列b高→第四列rCPU核数CPU瓶颈b0I/O瓶颈CPU高top -ctop -H -p PIDjstack/perf top找吃CPU的线程和调用栈内存高free -hsmem -p -s pssavailable持续下降内存不足内存泄漏smem观察趋势pmap -x PIDvalgrind进程PSS只涨不跌泄漏磁盘满df -hdu -sh /* 2/dev/null逐层深入df和du结果悬殊被删文件仍被占用磁盘满隐形df -hvsdu -shlsof L1查(deleted)文件并清空或kill -HUP网络异常ping -c 4 网关ss -tanp确认连通性和端口状态六、本篇小结排查黄金法则先宏观后微观先看全局uptime/vmstat/df锁定方向后再深入细节先排除最简单的原因磁盘满了、服务挂了、内存溢出了——这些远比代码bug更常见一次只验证一个假设不要同时改三个配置改完一个就验证否则不知道哪个生效了每一步保存证据script命令记录终端操作sar历史数据回溯问题发生时的系统状态三个高频故障的完整链路CPU飙升top找进程 →top -H找线程 →jstack/perf top看调用栈内存泄漏smem找进程 →pmap确认泄漏区域 →valgrind开发环境定位代码行磁盘隐形占用dfvsdu发现差异 →lsof L1找(deleted)文件 →truncate或kill -HUP释放动手练习bash# 1. 完整跑一次系统体检流程 uptime free -h df -h vmstat 2 5 # 2. 模拟“删除了文件但空间不释放”的场景 dd if/dev/zero of/tmp/bigdel bs1M count100 exec 3/tmp/bigdel # 打开一个文件描述符持有文件 rm /tmp/bigdel # 删除文件 df -h /tmp # 注意空间没释放 lsof L1 | grep bigdel # 找到这个“幽灵”文件 exec 3- # 关闭文件描述符空间释放 df -h /tmp # 验证空间已恢复 # 3. 观察进程的内存变化 smem -p -s pss | head -10七、下篇预告这是专栏的倒数第二篇文章。我们走过了50篇的技术学习——从第1篇的“为什么要学Linux”到第48篇的集群高可用从最基础的cd、ls命令到内核函数级别的动态追踪。最后一篇《专栏总结与Linux学习之路的未来展望》将回顾整条学习路径你可以对照每一篇的标题检查自己是否掌握核心操作和排查思路。我们将梳理Linux在当前技术生态中的角色演变——从传统的服务器操作系统到云计算的基础镜像、Kubernetes的容器运行时、AI训练平台的底层支撑并为你规划后续的深入方向容器编排、可观测性体系、内核开发等领域的学习路线图。这是整个专栏的终点也是你Linux技能持续生长的起点。