2036 字
10 分钟
swap解决npm构建内存不足的问题
2026-10-09

为什么总是在这里卡起?我在本地(windows)里就不会卡。gx@Ali-ECS:/var/repo/cypherx-blog-site$ npm run build npm warn Unknown project config “manage-package-manager-versions”. This will stop working in the next major version of npm. > cypherx-blog-site@0.0.1 build > astro build && pagefind —site dist 17:39:32 [content] Syncing content 17:39:33 [content] Synced content 17:39:34 [types] Generated 4.27s 17:39:34 [build] output: “static” 17:39:34 [build] mode: “static” 17:39:34 [build] directory: /var/repo/cypherx-blog-site/dist/ 17:39:34 [build] Collecting build info… 17:39:34 [build] ✓ Completed in 4.75s. 17:39:34 [build] Building static entrypoints…

Show less

17:40

卡在 “Building static entrypoints…” 这一步,这是 Astro 在用 Vite 打包,通常卡住的原因是服务器内存不足。

先看看服务器资源情况#

bash

Terminal window
# 开另一个 SSH 窗口,运行构建时观察内存
free -h
# 或者实时监控
top

阿里云 ECS 是什么配置?#

bash

Terminal window
# 查看 CPU 和内存
nproc # CPU 核心数
free -h # 内存

如果是 1核2G 或 1核1G,内存很可能不够 Astro 构建用。


临时解决:增加 swap 空间#

bash

Terminal window
# 创建 2G swap 文件
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# 验证
free -h

然后再试 npm run build,大概率能跑起来。


为什么本地不卡?#

本地 Windows 一般有 16G+ 内存,而阿里云入门级 ECS 可能只有 1-2G,Astro + Vite 构建时内存峰值很容易超出限制,进程就卡死了。

上面这一对操作的效果,机器重启后能保持吗

17:45

不能,重启后 swap 会失效。

让 swap 重启后自动挂载#

bash

Terminal window
# 把 swap 写入 /etc/fstab
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

验证是否写入成功#

bash

Terminal window
cat /etc/fstab | grep swap
```
看到这行说明成功:
```
/swapfile none swap sw 0 0

重启后验证 swap 是否自动生效#

bash

Terminal window
sudo reboot
# 重启后检查
free -h

看到 Swap 那行有数值就说明自动挂载成功了。

还是卡起了,是2G swap不够,还是?

17:46

先看看构建时的实际资源占用情况,开两个 SSH 窗口:

窗口1:运行构建

bash

Terminal window
npm run build

窗口2:实时监控资源

bash

Terminal window
# 每2秒刷新一次,观察内存和swap占用
watch -n 2 free -h

把窗口2的输出发给我,就能判断是内存不够还是其他问题。


同时也看看 CPU 和具体卡在哪个进程#

bash

Terminal window
# 窗口2 也可以用 top 看更详细的
top

按 M 键按内存排序,看哪个进程占用最多。

现在根本连不进第二个ssh

17:47

这说明服务器资源已经被榨干了,连 SSH 新连接都建立不了。

等构建结束或超时#

先等一会,构建要么成功,要么 OOM 被系统杀掉,之后 SSH 就能连进去了。


连进去后第一件事#

bash

Terminal window
# 看上次构建是否被 OOM killer 杀掉
dmesg | grep -i "oom\|killed"
# 查看内存和 swap 实际大小
free -h
# 查看服务器配置
nproc && free -h

把结果发给我,确认是内存问题还是别的。


可能的解决方向#

原因解决方式
内存真的不够增大 swap 到 4G,或升级 ECS 配置
Node.js 内存限制构建时增加 Node 内存上限
构建时其他进程占内存构建前先停掉 Nginx 等服务

其中增加 Node 内存限制可以先试试,不需要升级服务器:

bash

Terminal window
# 给 Node 分配更多内存再构建
NODE_OPTIONS="--max-old-space-size=1536" npm run build

等构建超时要等多久?

17:48

不一定,Astro 构建没有内置超时机制,会一直卡着直到:

  • ✅ 构建成功
  • ❌ OOM Killer 强制杀掉进程
  • ❌ 你手动终止

手动终止它#

既然第二个 SSH 连不进去,等当前这个 SSH 窗口恢复响应后,直接按:

Ctrl + C

如果 Ctrl + C 没反应,按:

Ctrl + Z

然后:

bash

Terminal window
# 强制杀掉 node 进程
kill -9 $(pgrep node)

恢复后马上试这个#

bash

Terminal window
# 限制 Node 内存,避免把服务器榨干
NODE_OPTIONS="--max-old-space-size=1024" npm run build

这样 Node 用超 1G 内存就会报错退出,而不是把整个服务器卡死。

OOM Killer是什么,它干什么的

17:49

OOM Killer 是什么#

OOM = Out Of Memory,OOM Killer 是 Linux 内核内置的一个机制,专门在内存耗尽时出来救场。


它解决什么问题#

Linux 内存用完后,如果不处理,整个系统会完全卡死,连键盘输入都没有响应。

OOM Killer 的作用就是:在系统内存耗尽前,主动杀掉最”该死”的进程,释放内存,让系统存活下去。

内存快耗尽
↓
OOM Killer 扫描所有进程
↓
计算每个进程的"分数"(占内存多、运行时间短、优先级低 → 分高)
↓
杀掉分数最高的进程
↓
内存释放,系统恢复正常

你的情况#

npm run build 启动
↓
Node.js 疯狂占用内存
↓
内存 + swap 全部耗尽
↓
OOM Killer 出现,杀掉 node 进程
↓
服务器恢复,SSH 可以连进去了

查看 OOM Killer 的记录#

bash

Terminal window
dmesg | grep -i "oom\|killed"
```
能看到类似:
```
Out of memory: Killed process 12345 (node) score 987

说明 node 进程确实被 OOM Killer 干掉了。

我把swap加大能不能解决问题?毕竟我不想再本地编译好后,把所有文件拷贝一次到服务器上,也不想每次再服务器上运行都写个NODE_OPTIONS=“—max-old-space-size=512”

17:57

可以解决,但 swap 比内存慢很多,构建会很慢。先看看你服务器实际内存:

bash

Terminal window
free -h
```
把结果发给我,根据实际情况给你最合适的建议。不同配置方案不一样:
| 服务器内存 | 建议 |
|-----------|------|
| 1G | 加 4G swap,但会很慢 |
| 2G | 加 2G swap,勉强够用 |
| 4G | 基本不需要 swap |
---
## 关于 NODE_OPTIONS 的问题
如果确认加 swap 能解决,可以把 `NODE_OPTIONS` 写进项目配置,这样每次构建自动生效,不用手动输入:
在项目根目录的 `.env` 文件里加:
```
NODE_OPTIONS=--max-old-space-size=1536

或者直接修改 package.json:

json

"scripts": {
"build": "NODE_OPTIONS=--max-old-space-size=1536 astro build && pagefind --site dist"
}

这样直接 npm run build 就自动带上了,不用每次手动写。

服务器是2 core 2g

17:58

2G 内存对 Astro 构建来说比较紧张,加上系统本身也要占用一部分。

bash

Terminal window
# 先看看现在实际可用多少
free -h

建议方案#

把 swap 加到 4G,2C2G + 4G swap 构建 Astro 应该够用,速度也不会太慢(2核 CPU 还不错)。

bash

Terminal window
# 先关掉现有的 2G swap
sudo swapoff /swapfile
# 删除旧的
sudo rm /swapfile
# 创建 4G swap
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# 验证
free -h

/etc/fstab 不需要改,之前已经写进去了,重启后自动生效。


同时把 NODE_OPTIONS 写进 package.json#

这样就彻底不用每次手动输入了:

json

"scripts": {
"build": "NODE_OPTIONS=--max-old-space-size=3072 astro build && pagefind --site dist"
}

3072M = 3G,让 Node 最多用 3G(内存+swap),既不会把系统榨干,又给构建足够空间。

你太聪明了,it works。那么我怎么把swap持久化?

18:06

之前已经写进 /etc/fstab 了,直接验证一下还在不在:

bash

Terminal window
cat /etc/fstab | grep swap
```
如果能看到:
```
/swapfile none swap sw 0 0

说明还在,重启后自动生效,不需要做任何操作。✅

我还没写呢

18:06

那现在写进去:

bash

Terminal window
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

验证一下:

bash

Terminal window
cat /etc/fstab | grep swap

看到 /swapfile none swap sw 0 0 就搞定了。✅

我发现,swap并没有用起来,还是要卡死

10:58

先看看 swap 是否真的在工作:

bash

Terminal window
# 构建时在另一个窗口观察
watch -n 2 free -h

或者构建完/卡死后:

bash

Terminal window
# 看 swap 有没有被使用过
free -h
# 看 swappiness 值(决定系统多积极使用 swap)
cat /proc/sys/vm/swappiness

把结果发给我,swappiness 默认值是 60,如果太低系统会不愿意用 swap。

gx@Ali-ECS:/var/repo/cypherx-blog-site$ cat /proc/sys/vm/swappiness 0

11:00

找到原因了!swappiness = 0 意味着系统几乎不会使用 swap,除非内存完全耗尽才会用,所以等于没用。

立即调高 swappiness#

bash

Terminal window
# 临时设置(立即生效)
sudo sysctl vm.swappiness=60
# 永久持久化(重启后保持)
echo 'vm.swappiness=60' | sudo tee -a /etc/sysctl.conf

swappiness 值的含义#

值含义
0几乎不用 swap,内存耗尽才用
60默认值,平衡使用
100积极使用 swap

你设置 60 就够了,然后再试 npm run build。

swap解决npm构建内存不足的问题
http://cypherx.top/posts/cs/使用swap解决npm构建内存不足卡死的问题/
作者
Cypherx
发布于
2026-10-09
许可协议
CC BY-NC-SA 4.0