当前位置:首页>Linux>Linux内存排查与分析实战

Linux内存排查与分析实战

  • 2026-09-08 14:58:51
Linux内存排查与分析实战

服务器内存告警了,打开top一看used很高,然后就不知道怎么查了。

这篇整理一下Linux内存排查的常用方法。

先看整体情况

free命令

free -h
              total        used        free      shared  buff/cache   available
Mem:           31Gi        18Gi       1.2Gi       234Mi        12Gi        12Gi
Swap:         2.0Gi       512Mi       1.5Gi

几个关键概念:

  • used:已使用的内存
  • free:完全空闲的内存
  • buff/cache:缓存和缓冲区
  • available:可用内存(重点看这个)

很多人看到free很低就慌了,其实不用。Linux会把空闲内存用来做缓存(buff/cache),这些内存在需要时可以被回收。

真正要关心的是available,它代表应用程序实际可用的内存。

为什么used高但没问题

free -h
# used: 28Gi
# free: 500Mi
# buff/cache: 10Gi
# available: 10Gi

虽然used显示28G,但其中10G是缓存。如果应用需要内存,系统会自动回收缓存。

只有available也接近0的时候才需要担心。

swap使用情况

free -h | grep Swap
# Swap:         2.0Gi       512Mi       1.5Gi

如果swap used不为0,说明物理内存不够用,系统把数据换到磁盘了。这会导致性能下降。

查看swap使用详情:

swapon --show

vmstat看内存趋势

vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  0 512000 123456 234567 789012    5   10   100   200  234  567  5  2 90  3  0

关键列:

  • swpd:使用的swap大小
  • si:从swap读入的数据量(KB/s)
  • so:写入swap的数据量(KB/s)

si和so持续不为0,说明在频繁使用swap,性能会受影响。

找出内存大户

top/htop

top

按 M 可以按内存排序。

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
12345 mysql     20   0   10.2g   8.5g   1234 S   5.2  27.4   1234:56 mysqld
23456 java      20   0    8.5g   6.2g    567 S  12.3  20.0    567:89 java

关键列:

  • VIRT:虚拟内存(不重要)
  • RES:实际物理内存(重点看这个)
  • SHR:共享内存
  • %MEM:内存占比

ps命令

# 按内存排序显示进程
ps aux --sort=-%mem | head -20

# 只看特定列
ps -eo pid,user,rss,vsize,comm --sort=-rss | head -20

smem

比ps更准确,考虑了共享内存的分摊:

# 安装
apt install smem  # 或 yum install smem

# 使用
smem -rs rss | head -20
  PID User     Command                         Swap      USS      PSS      RSS
12345 mysql    mysqld                             0  8234567  8345678  8567890
  • USS:进程独占的内存
  • PSS:按比例分摊共享内存后的大小
  • RSS:包含共享内存的总大小

看PSS比较准确。

分析单个进程

/proc文件系统

# 进程内存概况
cat /proc/12345/status | grep -E "^(VmSize|VmRSS|VmSwap)"
VmSize: 10485760 kB    # 虚拟内存
VmRSS:  8765432 kB    # 物理内存
VmSwap:   123456 kB    # 使用的swap

内存映射详情

# 简单版
cat /proc/12345/smaps_rollup

# 详细版
cat /proc/12345/smaps | head -100
7f1234560000-7f1234590000 rw-p 00000000 00:00 0                          [heap]
Size:                196 kB
Rss:                 180 kB
Pss:                 180 kB
...

pmap

pmap -x 12345 | tail -20
Address           Kbytes     RSS   Dirty Mode  Mapping
0000555555554000    1234     890     456 r-x-- mysqld
...
total kB        10485760 8765432  567890

具体问题排查

问题1:哪个进程在用swap

# 方法1:脚本
for pid in /proc/[0-9]*; do
    swap=$(awk '/VmSwap/{print $2}'$pid/status 2>/dev/null)
if [ -n "$swap" ] && [ "$swap" -gt 0 ]; then
        name=$(cat $pid/comm 2>/dev/null)
echo"$pid$name${swap}kB"
fi
done | sort -t: -k2 -n | tail -20

# 方法2:用smem
smem -rs swap | head -20

问题2:内存泄漏

如果某个进程的内存持续增长:

# 监控进程内存变化
whiletruedo
    ps -p 12345 -o pid,rss,vsz | tail -1
    sleep 60
done

对于Java应用,用jmap分析堆:

jmap -heap 12345
jmap -histo 12345 | head -30

对于C/C++应用,用valgrind。

问题3:buff/cache过高

正常情况下buff/cache高不是问题。如果想手动释放:

# 清理pagecache
echo 1 > /proc/sys/vm/drop_caches

# 清理dentries和inodes
echo 2 > /proc/sys/vm/drop_caches

# 清理所有
echo 3 > /proc/sys/vm/drop_caches

注意:生产环境不建议经常做,会导致缓存失效,IO突增。

问题4:OOM Killer

系统内存不够时会杀进程,查看被杀的进程:

# 查看OOM日志
dmesg | grep -i "out of memory"
grep -i "killed process" /var/log/messages

# 看哪个进程被杀
dmesg | grep -i oom | tail -20

调整进程被OOM Kill的优先级:

# 查看当前值(-1000到1000,越大越容易被杀)
cat /proc/12345/oom_score_adj

# 设置(-1000表示永不被杀)
echo -1000 > /proc/12345/oom_score_adj

问题5:内存碎片

长时间运行的系统可能有内存碎片:

cat /proc/buddyinfo
Node 0, zone   Normal  12345  6789  3456  1234   567   234   123    56    23     8     2

后面的数字代表各种大小的连续空闲页数量。如果小块很多、大块很少,说明碎片严重。

整理碎片:

echo 1 > /proc/sys/vm/compact_memory

优化配置

swappiness

控制系统使用swap的积极程度:

# 查看当前值(默认60)
cat /proc/sys/vm/swappiness

# 临时修改(0-100,越小越不爱用swap)
echo 10 > /proc/sys/vm/swappiness

# 永久修改
echo"vm.swappiness = 10" >> /etc/sysctl.conf
sysctl -p

数据库服务器通常设置成10或更低。

overcommit

控制内存申请策略:

# 查看
cat /proc/sys/vm/overcommit_memory

# 0:默认,内核自己判断
# 1:总是允许申请
# 2:不允许超过物理内存+swap

透明大页

有些应用(如数据库)建议关闭透明大页:

# 查看状态
cat /sys/kernel/mm/transparent_hugepage/enabled

# 临时关闭
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

命令速查

# 整体情况
free -h                 # 内存概况
vmstat 1                # 实时监控

# 进程排查
top                     # 按M排序
ps aux --sort=-%mem     # 内存排序
smem -rs rss            # 更准确

# 详细分析
cat /proc/PID/status    # 进程内存信息
pmap -x PID             # 内存映射

# OOM相关
dmesg | grep -i oom     # OOM日志
cat /proc/PID/oom_score_adj  # OOM优先级

# 清理缓存(慎用)
echo 3 > /proc/sys/vm/drop_caches

内存排查的核心:

  1. free看available,不是free
  2. top/ps找内存大户
  3. /proc/$PID/status看进程详情
  4. swap使用多要关注

平时没事别去清缓存,那是系统在帮你加速IO。

只有available低、swap频繁使用时才需要处理。

最新文章

随机文章