Ubuntu 16.04执行任意命令报bash: fork: Cannot allocate memory,如何系统层面预防?
这种因挂起任务耗尽内存,连ps、free这类基础命令都跑不起来的情况确实让人头疼——还好你留着SSH会话能救场,不然可能得硬重启了。针对Ubuntu 16.04,我整理了几个实用的系统层面预防措施,帮你避免再踩这个坑:
1. 优化OOM Killer,保护关键进程
Linux的OOM(Out-of-Memory) Killer默认会随机杀掉内存占用高的进程,但有时候会误杀sshd、bash这类能帮你救场的关键进程。我们可以调整进程的oom_score_adj值,让关键进程优先存活:
- 临时设置:给
sshd进程设置最低优先级(不会被OOM Killer选中):echo -1000 > /proc/$(pidof sshd)/oom_score_adj - 永久生效:编辑
/etc/rc.local,在exit 0前添加上面的命令,开机自动执行。
另外,调整内存过度提交参数,避免系统无限制分配内存:
- 临时生效:
sudo sysctl vm.overcommit_memory=2 - 永久生效:编辑
/etc/sysctl.conf,添加vm.overcommit_memory=2,然后执行sudo sysctl -p加载配置。
注:
vm.overcommit_memory=2表示系统只会分配不超过「物理内存 + swap空间」的内存,避免过度提交导致突然耗尽内存。
2. 优化Swap配置,增加内存缓冲
如果你的Swap空间不足,或者没配置合理的swappiness,会加速内存耗尽的情况:
扩容Swap文件(如果当前Swap不够)
# 创建4G的Swap文件 sudo fallocate -l 4G /swapfile # 设置权限,只有root能访问 sudo chmod 600 /swapfile # 格式化Swap文件 sudo mkswap /swapfile # 启用Swap sudo swapon /swapfile # 永久生效,添加到/etc/fstab echo "/swapfile none swap sw 0 0" | sudo tee -a /etc/fstab
调整Swappiness参数
Swappiness控制系统使用Swap的倾向,默认是60,建议设为10(尽量用物理内存,内存快耗尽时再用Swap):
# 临时生效 sudo sysctl vm.swappiness=10 # 永久生效,添加到/etc/sysctl.conf echo "vm.swappiness=10" | sudo tee -a /etc/sysctl.conf sudo sysctl -p
3. 监控内存使用,提前告警/自动清理
设置定时监控,当内存占用达到阈值时,主动告警或清理非关键进程:
编写内存监控脚本
创建/usr/local/bin/memory-monitor.sh:
#!/bin/bash # 内存占用阈值(百分比) THRESHOLD=15 # 获取当前内存占用百分比(整数) USED_MEM=$(free | awk '/Mem/{printf "%d", $3/$2 * 100}') if [ $USED_MEM -gt $THRESHOLD ]; then # 发送邮件告警(需要先安装mailutils:sudo apt install mailutils) echo "[$(date)] 服务器内存占用过高:${USED_MEM}%,请及时处理!" | mail -s "内存告警 - $(hostname)" your-email@example.com # 可选:自动终止内存占用TOP5的非root进程(谨慎使用,避免杀错关键进程) # ps aux --sort=-%mem | grep -v root | grep -v sshd | head -5 | awk '{print $2}' | xargs kill -TERM fi
给脚本加执行权限:
sudo chmod +x /usr/local/bin/memory-monitor.sh
配置Cron定时运行
编辑Cron任务:
sudo crontab -e
添加一行,每5分钟运行一次监控:
*/5 * * * * /usr/local/bin/memory-monitor.sh
4. 限制进程的内存使用
通过ulimit或cgroups,给特定用户或进程设置内存上限,避免单个进程耗尽内存:
用ulimit限制用户进程
编辑/etc/security/limits.conf,添加(替换your-username为实际用户名):
your-username hard rss 2097152 # 限制该用户的进程最多使用2G内存(单位KB)
用户重新登录后生效。
用cgroups精细控制进程组
安装cgroup工具:
sudo apt install cgroup-tools
创建一个内存限制的cgroup,比如限制最多用1G内存:
sudo cgcreate -g memory:/limit-mem sudo cgset -r memory.limit_in_bytes=1G limit-mem
之后要限制的进程可以用cgexec启动:
cgexec -g memory:/limit-mem your-process-command
5. 优化挂起任务管理
- 定期清理无用的挂起任务:用
jobs查看,kill %n(n是任务编号)清理不需要的任务; - 调整任务调度:把内存占用高的任务放到凌晨等低峰期运行,避免和业务进程抢内存;
- 优化任务本身:如果是自定义脚本,尽量减少内存占用(比如避免加载大文件到内存,及时释放变量等)。
内容的提问来源于stack exchange,提问作者EM0

