0

Linux内存不足问题解决方法:从排查到优化的完整实战指南

2026.05.21 | youres | 10次围观

一、Linux内存不足的常见表现

服务器内存不足时,通常会出现以下症状:

  • 进程被莫名杀掉:日志里出现 Out of memory: Kill process,这是OOM Killer在出手
  • 系统响应极慢:内存吃紧时系统疯狂换页,CPU花大量时间在swap操作上
  • 服务启动失败:比如MySQL报 Cannot allocate memory,Nginx起不来
  • ssh登录卡顿:连上去都费劲,敲个命令半天没反应

二、快速排查内存使用情况

1. free命令看全局

free -h

重点关注 available 列,这才是系统实际可用的内存。很多人看 buff/cache 占了一大堆就慌了,其实这部分内存系统随时可以回收,不必担心。

判断标准:available低于总内存的10%就该警惕了。

2. top/htop看进程占用

# 按内存排序
top -o %MEM
# 或者用htop更直观
htop --sort-key PERCENT_MEM

找出占内存最多的进程,心里就有数了。

3. 查看OOM Killer日志

# 查看系统日志中的OOM记录
dmesg | grep -i "out of memory"
dmesg | grep -i "killed process"
# 或者查syslog
journalctl -k | grep -i "oom"

OOM Killer会选择占用内存最大的进程杀掉,日志里会记录被杀进程的PID和内存占用。

4. 查看具体进程内存明细

# 查看进程的内存映射
pmap -x <PID>
# 查看进程的smaps详情
cat /proc/<PID>/smaps | head -100

三、临时应急方案

1. 清理缓存

# 清理page cache
sync && echo 1 > /proc/sys/vm/drop_caches
# 清理dentries和inodes
sync && echo 2 > /proc/sys/vm/drop_caches
# 全部清理
sync && echo 3 > /proc/sys/vm/drop_caches

生产环境慎用,清缓存只是治标,该占的内存还是会占回来。

2. 添加Swap空间

# 创建swap文件(4G为例)
dd if=/dev/zero of=/swapfile bs=1M count=4096
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile

# 验证
free -h
swapon --show

# 开机自动挂载
echo '/swapfile none swap sw 0 0' >> /etc/fstab

Swap大小建议:物理内存≤2G时,swap设为内存2倍;4-16G内存时,swap等于内存即可;16G以上,swap设4-8G足够。

3. 优化swap使用策略

# 查看当前swappiness值
cat /proc/sys/vm/swappiness
# 降低swappiness(默认60,服务器建议10-30)
sysctl vm.swappiness=10
# 永久生效
echo 'vm.swappiness=10' >> /etc/sysctl.conf
sysctl -p

swappiness值越低,系统越倾向于保留内存数据而非换到swap。服务器场景设10比较合适。

4. 重启占内存的服务

# 找出占内存最多的进程
ps aux --sort=-%mem | head -10
# 重启对应服务
systemctl restart nginx
systemctl restart mysql

四、长期优化方案

1. 优化应用内存配置

不同应用的内存优化思路不同:

  • MySQL:调低 innodb_buffer_pool_size,通常设为物理内存的50-70%
  • PHP-FPM:减少 pm.max_children,避免子进程过多吃光内存
  • Nginx:调低 worker_connectionsclient_body_buffer_size
  • Java应用:通过 -Xmx 限制JVM最大堆内存
  • Redis:设置 maxmemory 并配置淘汰策略

2. 排查内存泄漏

# 长期监控某个进程的内存变化
while true; do
  echo "$(date): $(ps -p <PID> -o rss=) KB"
  sleep 60
done

如果进程内存持续增长不释放,基本就是内存泄漏。常见原因:未关闭的数据库连接、缓存无限增长、大对象未回收。

3. 使用cgroup限制进程内存

# 创建cgroup并限制最大内存为512M
mkdir -p /sys/fs/cgroup/memory/myapp
echo 536870912 > /sys/fs/cgroup/memory/myapp/memory.limit_in_bytes
echo <PID> > /sys/fs/cgroup/memory/myapp/cgroup.procs

这样即使进程失控,也不会把系统内存吃光。

4. 设置OOM策略

# 查看当前OOM策略
cat /proc/sys/vm/overcommit_memory
# 0=启发式(默认),1=总是允许,2=严格不允许
# 生产环境建议设0或2
echo 0 > /proc/sys/vm/overcommit_memory

# 调整OOM Killer的优先级(数值越低越不容易被杀)
echo -500 > /proc/<PID>/oom_score_adj

5. 监控告警

别等问题来了才排查,提前设置监控:

# 简单的内存监控脚本
#!/bin/bash
THRESHOLD=90
USAGE=$(free | awk '/Mem:/{printf("%.0f"), $3/$2*100}')
if [ "$USAGE" -gt "$THRESHOLD" ]; then
  echo "内存使用率 ${USAGE}% 超过阈值 ${THRESHOLD}%" | mail -s "内存告警" admin@example.com
fi

有条件的建议上Zabbix或Prometheus做专业监控,可视化面板一目了然。

六、常见问题FAQ

Q:buff/cache很高需要清理吗?

不需要。Linux把空闲内存用来缓存磁盘数据是正常行为,应用需要内存时会自动释放。手动清cache反而降低性能。

Q:swap用了很多说明内存不够吗?

不一定。swappiness值高时系统会把不活跃的内存页换到swap,即使物理内存还有余量。检查available值才是关键。

Q:OOM Killer杀错了进程怎么办?

调整 oom_score_adj 值,给关键进程设置负值降低被杀概率。极端情况可以设 -1000 彻底禁止被OOM杀掉,但不建议滥用。

相关文章

版权声明

本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论
881文章数 0评论数
作者其它文章