2G 内存云服务器上
vite build频繁被杀,exit code 137 。排查发现不是内存不够,而是内核根本不用 swap 。
现象
在阿里云 2C2G 服务器上部署前端项目,pnpm build 执行到 vite build 阶段必失败:
vite v6.4.3 building for production...
✓ 2592 modules transformed.
sh: line 1: 1227505 Killed
[ELIFECYCLE] Command failed with exit code 137.
exit code 137 = 128 + 9 (SIGKILL)——进程被系统强制杀死。
部署日志显示构建前内存使用率已达 80%+:
host metrics | cpu: 77.3% | ram usage: 80.2%
第一反应:内存不足
服务器总内存 1870MB,部署时:
- PM2 cluster 2 个 worker:~300MB
- 系统进程:~500MB
- pnpm install 缓存:~200MB
- 可用物理内存:~870MB
Vite build 峰值需要 ~1.5GB,物理内存确实不够。
尝试 1:限制 Node.js 堆内存
export NODE_OPTIONS="--max-old-space-size=1024"
pnpm build
结果:仍然 OOM 。
原因:--max-old-space-size 只限制 V8 堆 (JS 对象),不限制进程总内存 (RSS) 。 Node.js 总内存 = V8 堆 + C++ 层 + esbuild/rollup 原生缓冲区 + 线程栈。 OOM Killer 看的是 RSS,不是 V8 堆。
尝试 2:创建 swap
dd if=/dev/zero of=/swapfile2 bs=1M count=4096
chmod 600 /swapfile2
mkswap /swapfile2
swapon /swapfile2
验证:swapon --show 显示 5GB swap,free -h 显示 Swap 总量 5.0Gi 。
结果:仍然 OOM!
这就诡异了。 5GB swap + 1.87GB 物理内存 = 6.87GB 虚拟内存,vite build 峰值 1.5GB 远够用,为什么还被杀?
真凶:swappiness=0
检查内核参数:
cat /proc/sys/vm/swappiness
# 0
swappiness=0——这就是根因。
什么是 swappiness
vm.swappiness 是 Linux 内核参数,控制内核使用 swap 的积极程度:
| 值 | 行为 |
|---|---|
| 0 | 几乎不使用 swap,优先回收文件缓存页,物理内存耗尽直接 OOM |
| 1-60 | 平衡使用 swap |
| 60 | 默认值,适度使用 swap |
| 100 | 积极使用 swap |
为什么云服务器默认 swappiness=0
阿里云、腾讯云等云服务商默认将 swappiness 设为 0,理由是:
- swap 在磁盘上,速度比物理内存慢 100-1000 倍
- 对性能敏感的生产服务 (数据库/API),使用 swap 会导致严重延迟
- 宁可 OOM 重启进程,也不要拖慢整个系统
这个策略对常驻服务 (Nginx/MySQL/API) 合理,但对短时高内存任务(如 vite build) 是灾难——build 只需要 1-2 分钟峰值内存,完全可以用 swap 换过去,但 swappiness=0 让内核宁愿杀进程也不用 swap 。
修复
# 立即生效
sysctl vm.swappiness=60
# 持久化 (重启后仍生效)
echo 'vm.swappiness=60' >> /etc/sysctl.conf
修复后 vite build 正常完成,swap 使用约 800MB,构建时间比纯物理内存慢约 30%,但不再被杀。
完整排查路径
vite build exit 137 (OOM)
│
├─ 物理内存不足?→ 是 (2G 服务器,build 峰值 1.5G)
│
├─ 限制 V8 堆 → 无效 (OOM Killer 看 RSS 不看 V8 堆)
│
├─ 创建 swap → 无效 (swappiness=0,内核不用 swap)
│
└─ 设置 swappiness=60 → ✅ 成功
部署脚本优化
在 deploy.sh 中添加 swap 依赖说明和堆内存限制:
# 前端构建
export NODE_OPTIONS="--max-old-space-size=1024"
pnpm build
unset NODE_OPTIONS
并在文档中标注前提条件:
前提:
swappiness=60(否则 swap 不生效),见/etc/sysctl.conf
三层防护
对于小内存服务器的前端构建,建议三层防护:
- Swap(最关键):4GB+ swap +
swappiness=60,提供虚拟内存空间 - NODE_OPTIONS(辅助):
--max-old-space-size=1024,让 V8 GC 更积极 - 构建前释放内存 (可选):
pm2 stop暂停后端 worker,构建后pm2 start
三者中 swap 是根本解,其余是辅助。
总结
| 现象 | 根因 | 解法 |
|---|---|---|
| vite build exit 137 | OOM Killer 杀进程 | 增加 swap |
| 有 swap 仍 OOM | swappiness=0,内核不用 swap | sysctl vm.swappiness=60 |
| NODE_OPTIONS 无效 | 只限 V8 堆,不限进程 RSS | 依赖 swap 而非堆限制 |
教训:在云服务器上跑前端构建,先检查 cat /proc/sys/vm/swappiness 。如果是 0,再大的 swap 也是摆设。

Comments NOTHING