CLI AI

找出内存持续增长的进程

2026-05-08

"占用大量内存"和"内存泄漏"是两个不同的问题。泄漏是指进程的 RSS 持续上升、从不下降,即使机器处于空闲状态也是如此。单次快照看不出这一点——需要间隔一段时间取两次快照。

1. 现在谁占用的内存最多

clai
$ clai 按内存使用量列出进程→ ps -eo pid,comm,rss,%mem --sort=-rss | head -4    PID COMMAND           RSS %MEM 218979 firefox       2089376  3.1 269458 verba         1257196  1.9 727108 telegram      1249824  1.9

RSS 以 KB 为单位,是真正重要的数字:实际占用的物理内存。这只是嫌疑名单,不是答案。

2. 随时间观察单个进程

clai
$ clai 每 10 秒采样一次 pid 269458 的内存,共 6 次→ pidstat -r -p 269458 10 6

这才是真正的测试。负载平稳的情况下,六次采样都在上升就是泄漏。上升后趋于平稳则是缓存在填充,属于正常现象,会自行停止。

3. 不装额外软件包的低成本采样

clai
$ clai 把这个进程的内存每分钟记录到文件→ while sleep 60; do printf '%s %s\n' "$(date +%T)" "$(grep VmRSS /proc/269458/status)"; done | tee mem.logVmRSS:	  1257196 kB

pidstat 属于 sysstat 软件包,不一定已安装。/proc/<pid>/status 则始终存在。让它跑上一小时,答案的走势就会一目了然。

4. 内存具体去了进程的哪里

clai
$ clai 显示 pid 269458 的内存映射,按大小排序→ sudo pmap -x 269458 | sort -k3 -rn | head

如果某个匿名映射在两次 pmap 运行之间不断增大,那就是堆。大量不断增多的小映射通常意味着线程栈泄漏或未关闭的 mmap 文件。

5. 先排除文件缓存

clai
$ clai 显示不含缓存和缓冲区的内存使用情况→ free -h               total        used        free      shared  buff/cache   availableMem:            62Gi        18Gi       2.1Gi       1.2Gi        42Gi        43Gi

要看 available,不是 free。Linux 会故意用页面缓存填满空闲内存,并按需释放。"只剩 2 GB 空闲"而 available 有 43 GB,这是健康的系统,不是泄漏。

6. 确认问题出在进程而非整机

clai
$ clai 检查内核是否因内存不足杀掉过进程→ sudo dmesg -T | grep -i 'killed process'

如果 OOM killer 触发过,内核会记录它选中的进程以及当时的内存占用。这是你能拿到的最有力的证据,而且已经替你写好了。

常见误区

  • RSS 会重复计算共享内存。 两个共享同一库的进程都会各自报告那些页面。要得到每个进程的真实数字,使用 smem 或 /proc/<pid>/smaps_rollup 里的 PSS。
  • 重启只是权宜之计,不是诊断。 它会清空曲线、抹去证据。先采样,再重启。
  • 容器限制在容器内部看不到。 容器里的进程通过 free 看到的是宿主机的总内存;真正的上限记在 /sys/fs/cgroup/memory.max 里。

相关问题

多大的增长算泄漏? 只要在负载平稳时持续向上就算。一个每小时多占 50 MB 且从不释放的进程,无论加多少内存,迟早都会触发 OOM killer。

Linux 上内存占用高本身是坏事吗? 不算。闲置的内存就是浪费的内存——内核会用它做缓存,并在有压力时回收。应该关注的是 available 和交换分区的活动情况。

用什么工具能找到具体泄漏的代码行? C/C++ 用 Valgrind(--leak-check=full),其他语言用各自的堆分析器。这里的命令能找到是哪个进程;修复它要用别的工具。

另请参阅

告诉 CliAI 你想测量什么,它会写出你原本要去查的 pidstat 调用。一行命令安装。