Swap占用高不等于内存不足,关键看available是否持续低于500MB、si/so是否持续大于100、是否存在VSZ远大于RSS的进程;需结合vm.swappiness配置与进程虚拟内存行为综合判断。

Swap占用高不等于内存不够,更可能是内核在“主动腾地方”——尤其当vm.swappiness设得太高、或某些进程虚占大量虚拟内存(VSZ远大于RSS)时。先别急着加内存或扩Swap,得先确认是不是真缺RAM,还是配置/进程在捣鬼。
怎么快速判断是真内存不足还是假警报
光看free -h的available值容易误判。关键要看三组数据是否同时异常:
-
available低于500MB(对8GB内存机器而言),且buff/cache没明显下降 → 真缺物理内存 -
si和so持续大于100(用vmstat 1看)→ 正在频繁换页,性能已受损 - 某个进程
VSZ高达几GB但RSS只有几十MB(用ps -eo pid,vsz,rss,comm --sort=-vsz | head -5查)→ 它申请了大量虚拟内存,却只用了极少物理内存,内核把它“冷处理”进了Swap
比如宝塔面板的BT-Task进程常出现这种现象:VSZ 1.1GB,RSS仅29MB,却占了500MB Swap —— 这不是它吃内存,是内核觉得它“冷”,优先往Swap里扔。
临时止血:立刻降低Swap倾向
如果si/so飙高、系统卡顿,先压住换页冲动:
- 临时生效(重启失效):
sudo sysctl vm.swappiness=10 - 别设成0:设0后内核几乎不swap,但OOM Killer可能突然杀掉关键进程,生产环境风险大
- 观察效果:改完立刻跑
vmstat 1,so应明显回落;free -h里Swap used不会马上降,但新增换出会变少
注意:swappiness=10意味着内核等到物理内存只剩10%余量时才开始swap,比默认60更保守,适合多数服务器。
定位并清理真正吃Swap的进程
不能只看%MEM排序,得找“Swap实际用量高”的进程:
- 用这个命令直接列出Swap占用前10的进程:
for proc in /proc/[0-9]*; do pid=$(basename $proc); swap=$(awk '/VmSwap/ {print $2}' $proc/status 2>/dev/null); [ "$swap" != "0" ] && [ -n "$swap" ] && echo "$pid $swap $(cat $proc/cmdline 2>/dev/null | tr '\0' ' ' | head -c 50)"; done 2>/dev/null | sort -k2nr | head -10 - 结果里
swap列单位是KB,>100000(即100MB)就值得重点查 - 常见嫌疑对象:
java(Xmx设太大)、python脚本(如宝塔任务)、docker容器(未限制内存)、redis(maxmemory未配或配错) - 确认后,可
kill -9 PID重启服务,或进其配置调低内存上限(如Java改-Xmx,Redis改maxmemory)
别依赖top或htop的默认视图——它们默认不显示Swap用量,容易漏掉“表面安静、背后狂swap”的进程。
永久生效与长期预防
临时调参治标,写入配置才治本:
- 编辑
/etc/sysctl.conf,追加一行:vm.swappiness=10 - 执行
sudo sysctl -p加载,再用cat /proc/sys/vm/swappiness验证 - 检查
/etc/fstab里Swap条目是否有sw选项(确保开机启用),但别盲目扩Swap文件——Swap过大反而延长OOM前的挣扎时间,掩盖真实问题 - 对Java/Python服务,务必在启动脚本里显式限制内存,例如Java加
-Xmx2g -XX:+UseG1GC,避免JVM无节制申请虚拟内存
最易被忽略的一点:Swap占用高往往不是孤立现象,而是内存管理链上某环松动的结果——比如一个Python脚本没释放数据库连接池,导致连接对象堆积在内存里不回收,最终被swap出去。所以查到高Swap进程后,一定要顺藤摸瓜看它的资源使用逻辑,而不是只 kill 了事。


















