Linux 内存被谁吃掉了?用 free、top 与 smem 定位内存占用的完整做法
服务器内存告警是最常见的运维电话之一。很多新手看到监控里内存用了 90% 就慌着加内存,其实先要分清:内存是真的被业务吃掉了,还是被系统拿去当缓存了。下面这套流程,照着走一般十分钟就能定位。
第一步,先看 free -h,别被 used 吓到。执行 free -h,重点看 available 这一列,而不是 used。Linux 会把空闲内存拿去做磁盘缓存(buff/cache),used 里包含了这部分缓存。available 才是真正还能分配给新进程的内存。举个例子:总内存 8G,used 显示 7.2G,但 available 还有 3.5G,这台机器其实并不缺内存,不用处理。反过来,如果 available 只剩几百 MB,同时 swap used 在持续增长,那才是真的吃紧,需要往下查。
第二步,找出吃内存的进程。top 打开后按 Shift+M,按内存占用排序,第一屏就能看到最耗内存的进程。更适合写进排查记录的是 ps 命令:ps aux --sort=-%mem | head -n 15,会按内存占比倒序列出前 15 个进程,包含 USER、PID、%MEM、RSS 和完整命令行。注意看 RSS 这一列,它是进程实际占用的物理内存;VSZ 是虚拟内存,包含了共享库和映射文件,不能直接当成真实占用。重点关注两类进程:一是 RSS 持续增长、重启后又慢慢涨上来的,这往往是内存泄漏;二是突然冒出来的陌生进程,可能是跑飞的定时任务或者被植入的挖矿程序,先确认身份再处理。
第三步,共享内存会重复计算,要用 PSS 校准。Java、Python 多进程这类应用,多个进程共享同一份库文件,ps 里每个进程的 RSS 都会把共享部分重复算进去,加总会虚高。这时用 smem -s pss 看 PSS(按比例分摊后的内存),或者对单个进程用 pmap -x 进程号,看 Anonymous 匿名内存和共享段的分布。判断标准很简单:PSS 总和接近 free 的 used 减去 buff/cache,才是业务真实占用;如果 PSS 加总远小于 used,差额多半在页缓存里,不用处理。
第四步,定位三类常见元凶。第一类是应用内存泄漏:用 ps 每隔一小时记录一次 RSS,画出趋势,持续单调上涨基本可以定性,处理办法是重启进程止血,再结合应用的堆转储或 profiling 工具定位泄漏点。第二类是缓存类服务配置过大:Redis 的 maxmemory、MySQL 的 innodb_buffer_pool_size、JVM 的 -Xmx,这些上限加起来超过物理内存就会互相挤压,按业务优先级逐个调小。第三类是系统层面:检查 dmesg | grep -i oom,看最近有没有进程被 OOM Killer 杀掉;用 vmstat 1 看 si/so 两列,swap 换入换出持续大于 0,说明内存已经不够用了。
第五步,处理与注意事项。确认是泄漏的进程,先重启恢复业务,再修代码,不要在线上反复试参数。确认是缓存配置问题,改完配置要重启对应服务并观察一小时。不要在生产环境随便执行 echo 3 > /proc/sys/vm/drop_caches 清缓存,它只会让缓存失效、短时间内磁盘 IO 飙升,解决不了真正的内存不足。最后把排查结论记下来:哪天、哪个进程、RSS 涨到多少、采取了什么措施,下次同类告警直接对照,十分钟能解决的事不要每次都从头查。
- 点赞
- 收藏
- 关注作者
评论(0)