Linux内存泄漏排查方法:从症状到根因的服务排查教程
Linux内存泄漏排查方法:从症状到根因的服务排查教程
服务器跑着跑着,内存越占越多,最后OOM killer把进程杀死——这是典型的内存泄漏场景。
本文面向零基础运维,用最常用的Linux命令,一步步教你定位泄漏进程、分析内存增长原因,并确认修复效果。
1. 先看症状:内存涨了还是真的泄漏?
登录服务器后先执行 free -m 查看整体内存情况:
free -m
关注 available 列。
如果available持续下降、swap使用量上升,同时没有明显业务高峰,就可能是泄漏。
注意区分cache/buffer(会被回收),不要只看used。
用 uptime 看系统运行时间和负载,配合 dmesg 检查是否有OOM Killer日志:
dmesg | grep -i "oom"
如果出现 "Out of memory" 或 "Killed process",说明内存已经吃紧。
2. 定位可疑进程:找到谁在“吃”内存
先安装必要工具(一般系统自带):
sudo apt install htop pmap # Debian/Ubuntu
sudo yum install htop pmap # CentOS/RHEL
用 top 实时观察进程内存变化(按 M 键按内存排序):
top -o %MEM
看 RES(常驻内存)是否随着时间不断增加。
如果某个进程的RES每秒上涨几MB甚至几十MB,基本就是它泄漏了。
再执行 ps 命令列出内存占用最高的前几个进程:
ps aux --sort=-%mem | head -20
重点关注VSZ(虚拟内存)和RSS(物理内存)的比例。
VSZ很大但RSS正常,不一定是泄漏;
RSS持续快速增长才是信号。
3. 深入分析:用pmap看进程内存映射
拿到可疑进程PID后,用 pmap -x PID 查看地址空间:
pmap -x 12345
输出中 RSS 列是实际占用的物理内存,Dirty 列是脏页。
如果发现某个内存段(比如 [heap] 或匿名映射)的RSS异常大,且持续增长,那就是泄漏区域。
比如Java应用泄漏经常体现在堆(Heap)或直接内存(DirectBuffer)上。
可以进一步用 cat /proc/PID/status 查看 VmRSS 和 VmPeak:
cat /proc/12345/status | grep -E "VmRSS|VmPeak|VmSize"
VmPeak记录了进程历史最大内存,如果VmRSS不断接近甚至超过VmPeak,说明泄漏严重。
4. 跟踪内存分配:用strace和valgrind做深度排查
如果pmap无法定位到代码层面,可以用 strace 跟踪系统调用:
strace -p 12345 -e trace=brk,mmap,munmap
brk是C库堆分配,mmap是映射文件或匿名内存。
连续多次brk增加且没有munmap,基本就是堆泄漏。
对于严重泄漏,可以安装valgrind(影响性能,建议测试环境使用):
valgrind --tool=memcheck --leak-check=full ./your_program
但生产环境直接strace加pmap通常够用。
5. 避坑与高频问题
- 误区:RES高不一定是泄漏——有些应用(如数据库)会正常使用大量内存作为缓存,可以用
/proc/meminfo的MemAvailable判断。 - 误区:重启进程就行——治标不治本,长期累积会继续泄漏,必须定位到代码或配置。
- 实际场景:Java进程泄漏时,可以用
jstat -gcutil PID观察堆内存使用,或者加上-XX:+PrintGCDetails看GC日志。 - 避免误杀:如果怀疑是系统进程(如systemd-journald),先查阅文档确认它的正常行为,再决定是否处理。
6. 效果验证:确认泄漏已修复
修复后(比如重启服务、打补丁、调整配置),观察至少一个业务高峰周期:
free -m -s 30 # 每30秒输出一次
对比修复前后的内存曲线。
如果可用内存保持稳定,不再持续下降,说明问题解除。
同时检查进程的RSS是否不再增长,可以用 watch -n 10 'ps -p PID -o rss --no-headers' 持续监控。
总结:内存泄漏排查记住三条——先用 free -m 看整体,再用 top 或 ps 找异常进程,最后用 pmap 看内存映射定位泄漏区域。
按这条路径走,绝大多数泄漏都能快速锁定。