4.7.5 OOM机制与内存泄漏排查
本节聚焦 Linux 的 OOM 触发机制与内存泄漏排查方法,目标是理解系统在内存耗尽时的决策过程,掌握快速定位高风险进程与泄漏根因的手段,并形成可操作的处置流程。
一、OOM 触发条件与判定逻辑
当物理内存与可回收页缓存不足、且交换空间耗尽或被限制时,内核会触发 OOM Killer。判定通常基于以下要素:
- 进程内存占用(RSS、匿名页、共享页)
- 进程优先级与 oom_score_adj(越大越容易被杀)
- 系统当前内存回收效果与失败情况
- cgroup 限制下的局部 OOM(容器常见)
关键日志定位与解释示例
# 1) 快速查看内核OOM日志(含被杀进程与分值)
dmesg -T | egrep -i 'out of memory|killed process'
# 2) 查看系统日志(不同发行版路径可能不同)
grep -i 'out of memory' /var/log/messages
grep -i 'killed process' /var/log/kern.log
预期效果:输出包含 Out of memory 与 Killed process <pid> 的记录,可定位具体进程与时间。
二、OOM 排查与处置流程(含命令示例)
1. 确认是否 OOM
dmesg -T | tail -n 200 | egrep -i 'out of memory|killed process'
解释:从内核环形缓冲区获取 OOM 记录,确认是否被 OOM Killer 触发。
- 评估全局与 cgroup 限制
# 全局内存
free -m
vmstat 1 5
cat /proc/meminfo | egrep 'MemTotal|MemFree|MemAvailable|SwapTotal|SwapFree'
# cgroup(容器/服务)
cat /sys/fs/cgroup/memory/memory.limit_in_bytes
cat /sys/fs/cgroup/memory/memory.usage_in_bytes
解释:确认是否是全局内存耗尽还是被 cgroup 限制导致局部 OOM。
- 识别高风险进程
# 按RSS排序
ps aux --sort=-rss | head -n 10
# 实时观察内存增长
top -p <pid>
解释:RSS 持续增长、且与业务负载无关的进程为重点怀疑对象。
- 快速止血(短期缓解)
# 临时创建并启用2G swap(若磁盘充足)
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
swapon --show
解释:在不影响业务的情况下扩展 swap,降低瞬时 OOM 风险。
- 根因定位与修复
- 结合应用日志、内存快照与曲线分析定位泄漏点
- 逐步缩小范围:进程级 → 模块级 → 代码级
三、内存泄漏排查方法(含示例与解释)
1. 基线与趋势
# 每5秒记录一次RSS到文件
while true; do
date '+%F %T' >> /tmp/rss.log
ps -p <pid> -o pid,cmd,rss,vsz >> /tmp/rss.log
sleep 5
done
解释:若 RSS 单调增长且业务负载稳定,疑似泄漏。
- 进程级分析
# 查看映射段与匿名内存
pmap -x <pid> | tail -n 20
# 细分堆、栈、匿名页、共享库占用
grep -E 'Heap|Stack|Anon' /proc/<pid>/smaps | head -n 50
解释:匿名内存持续增加通常指向堆泄漏或缓存未释放。
- 句柄泄漏排查(可能间接导致内存增长)
# 统计打开文件数
ls /proc/<pid>/fd | wc -l
# 查看打开的具体文件
lsof -p <pid> | head -n 20
解释:FD 数持续增长可能引发内存与资源耗尽。
- 内存分配行为分析(自研可控程序)
# 观察分配热点(需安装perf)
perf top -p <pid>
解释:定位异常频繁的分配函数或模块。
工具安装示例(perf)
# RHEL/CentOS
yum install -y perf
# Ubuntu/Debian
apt-get update && apt-get install -y linux-tools-$(uname -r)
四、关键指标与判断依据(带命令)
# 进程内存:RSS/VSZ
ps -p <pid> -o pid,comm,rss,vsz
# PSS(共享内存摊分)
grep -E '^Pss:' /proc/<pid>/smaps | awk '{sum+=$2} END {print sum " KB"}'
# Swap 使用情况
free -m | egrep 'Mem|Swap'
解释:RSS 更直接反映泄漏;VSZ 仅表示虚拟地址空间;PSS 更准确评估共享内存占用。
五、常见误判与规避
- 页缓存增长:buff/cache 增加不等同泄漏,需关注 MemAvailable
- GC 语言:堆扩张≠泄漏,需结合 GC 日志与堆指标
- mmap 文件常驻:需结合 smaps 判断是否可回收
六、配置与防护建议(含示例)
# 降低关键进程被杀概率(-1000最不易被杀)
echo -1000 > /proc/<pid>/oom_score_adj
# 调整 swappiness(建议10~30)
sysctl -w vm.swappiness=10
echo 'vm.swappiness=10' >> /etc/sysctl.conf
解释:合理设置 oom_score_adj 保护核心进程,降低短时峰值导致的 OOM。
七、排错清单(故障定位顺序)
1) 是否出现 Out of memory 日志
2) 是否为 cgroup 限制导致
3) 是否有单个进程 RSS 单调增长
4) 是否 FD/线程数异常增长
5) 是否为缓存/队列无上限
八、练习(实操建议)
1) 使用 stress 触发内存压力并观察 OOM 迹象
# 安装stress
yum install -y stress || apt-get install -y stress
# 触发内存压力(谨慎在测试环境)
stress --vm 2 --vm-bytes 1G --timeout 30s
dmesg -T | tail -n 50
2) 选择一个进程,记录 1 分钟 RSS 变化并判断是否稳定
3) 使用 pmap 与 smaps 找出该进程占用最大的内存段
4) 调整 vm.swappiness 前后对 swap 使用的影响
通过以上方法,可将 OOM 从“事后事故”转变为“可预警、可定位、可修复”的可控问题,提升系统稳定性与可维护性。