Cannot allocate memory与OOM排查
约 687 字大约 2 分钟
2026-08-29
fork: Cannot allocate memory 和 Out of memory (OOM) 都指向"资源分配失败",但原因完全不同:前者多数时候内存明明还够,是进程数/线程数到了上限;后者是内存真的耗尽,内核强制杀进程保命。先分清类型再处理。
快速分型
| 现象 | 类型 |
|---|---|
free -h 显示 available 充足,但建进程/线程报 Cannot allocate memory | 限额型(进程数上限) |
dmesg 里有 Out of memory: Killed process ...,服务莫名消失 | 内存耗尽型(OOM) |
| VNC/SSH 登录报 Cannot allocate memory,机器只剩几 MB 内存 | 内存耗尽型 |
内存耗尽型:OOM
# 确认发生过 OOM,以及内核杀了谁
sudo dmesg | grep -i -E 'out of memory|oom'
# 找出内存占用前几名的进程
ps aux --sort=-%mem | head处理思路:
- 找出内存大户:常见为数据库缓存参数过大、程序内存泄漏、PHP-FPM/Java 子进程数过多。逐一核对配置(如 MySQL
innodb_buffer_pool_size、Java-Xmx)。 - 临时兜底:配置 Swap 换取缓冲时间,参见配置Swap与虚拟内存。注意 Swap 只是缓冲,长期不足仍需优化或升级配置。
- 业务确实增长:升级内存规格。
- 预防:核心服务用 systemd
MemoryMax=或容器内存限制隔离,避免单个进程拖垮整机;监控内存使用率(见Linux资源查看基础命令)。
内存没满也触发 OOM?
极少数情况是内核的 min_free_kbytes 保留水位设置过大,或程序申请超大块连续内存被拒绝。一般无需调整;确需处理时先排查程序本身的申请模式。
限额型:fork: Cannot allocate memory
内存充足却建不了新进程,按顺序检查三个上限:
# 1. 当前 shell 的进程数上限
ulimit -u
# 2. 系统级总进程/线程数
cat /proc/sys/kernel/threads-max
cat /proc/sys/kernel/pid_max
# 3. 是哪个用户到顶了:统计各用户进程数
ps -eo user | sort | uniq -c | sort -rn | head某用户进程数贴着
ulimit -u上限:修改该服务的限制,写法与排错思路同Too many open files与limits.conf不生效(文件句柄与进程数是同一套 limits 机制)。pid_max 偏小(如默认 32768,业务并发高):
sudo sysctl -w kernel.pid_max=4194303 # 持久化写入 /etc/sysctl.d/99-custom.conf:kernel.pid_max = 4194303Docker/容器环境:检查是否被 cgroup 的 pids 限制(
docker inspect查看PidsLimit)。
登录都进不去时
如果 SSH/VNC 都因 Cannot allocate memory 登不上,只能通过控制台强制重启实例,开机后立即按上面的步骤定位大户并处理,否则很快会复发。系统整体卡顿类问题参见Linux系统卡顿排查。
