为什么总是在这里卡起?我在本地(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
# 开另一个 SSH 窗口,运行构建时观察内存free -h
# 或者实时监控top阿里云 ECS 是什么配置?
bash
# 查看 CPU 和内存nproc # CPU 核心数free -h # 内存如果是 1核2G 或 1核1G,内存很可能不够 Astro 构建用。
临时解决:增加 swap 空间
bash
# 创建 2G swap 文件sudo fallocate -l 2G /swapfilesudo chmod 600 /swapfilesudo mkswap /swapfilesudo swapon /swapfile
# 验证free -h然后再试 npm run build,大概率能跑起来。
为什么本地不卡?
本地 Windows 一般有 16G+ 内存,而阿里云入门级 ECS 可能只有 1-2G,Astro + Vite 构建时内存峰值很容易超出限制,进程就卡死了。
上面这一对操作的效果,机器重启后能保持吗
17:45
不能,重启后 swap 会失效。
让 swap 重启后自动挂载
bash
# 把 swap 写入 /etc/fstabecho '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab验证是否写入成功
bash
cat /etc/fstab | grep swap```
看到这行说明成功:```/swapfile none swap sw 0 0重启后验证 swap 是否自动生效
bash
sudo reboot
# 重启后检查free -h看到 Swap 那行有数值就说明自动挂载成功了。
还是卡起了,是2G swap不够,还是?
17:46
先看看构建时的实际资源占用情况,开两个 SSH 窗口:
窗口1:运行构建
bash
npm run build窗口2:实时监控资源
bash
# 每2秒刷新一次,观察内存和swap占用watch -n 2 free -h把窗口2的输出发给我,就能判断是内存不够还是其他问题。
同时也看看 CPU 和具体卡在哪个进程
bash
# 窗口2 也可以用 top 看更详细的top按 M 键按内存排序,看哪个进程占用最多。
现在根本连不进第二个ssh
17:47
这说明服务器资源已经被榨干了,连 SSH 新连接都建立不了。
等构建结束或超时
先等一会,构建要么成功,要么 OOM 被系统杀掉,之后 SSH 就能连进去了。
连进去后第一件事
bash
# 看上次构建是否被 OOM killer 杀掉dmesg | grep -i "oom\|killed"
# 查看内存和 swap 实际大小free -h
# 查看服务器配置nproc && free -h把结果发给我,确认是内存问题还是别的。
可能的解决方向
| 原因 | 解决方式 |
|---|---|
| 内存真的不够 | 增大 swap 到 4G,或升级 ECS 配置 |
| Node.js 内存限制 | 构建时增加 Node 内存上限 |
| 构建时其他进程占内存 | 构建前先停掉 Nginx 等服务 |
其中增加 Node 内存限制可以先试试,不需要升级服务器:
bash
# 给 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
# 强制杀掉 node 进程kill -9 $(pgrep node)恢复后马上试这个
bash
# 限制 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
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
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
# 先看看现在实际可用多少free -h建议方案
把 swap 加到 4G,2C2G + 4G swap 构建 Astro 应该够用,速度也不会太慢(2核 CPU 还不错)。
bash
# 先关掉现有的 2G swapsudo swapoff /swapfile
# 删除旧的sudo rm /swapfile
# 创建 4G swapsudo fallocate -l 4G /swapfilesudo chmod 600 /swapfilesudo mkswap /swapfilesudo 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
cat /etc/fstab | grep swap```
如果能看到:```/swapfile none swap sw 0 0说明还在,重启后自动生效,不需要做任何操作。✅
我还没写呢
18:06
那现在写进去:
bash
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab验证一下:
bash
cat /etc/fstab | grep swap看到 /swapfile none swap sw 0 0 就搞定了。✅
我发现,swap并没有用起来,还是要卡死
10:58
先看看 swap 是否真的在工作:
bash
# 构建时在另一个窗口观察watch -n 2 free -h或者构建完/卡死后:
bash
# 看 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
# 临时设置(立即生效)sudo sysctl vm.swappiness=60
# 永久持久化(重启后保持)echo 'vm.swappiness=60' | sudo tee -a /etc/sysctl.confswappiness 值的含义
| 值 | 含义 |
|---|---|
0 | 几乎不用 swap,内存耗尽才用 |
60 | 默认值,平衡使用 |
100 | 积极使用 swap |
你设置 60 就够了,然后再试 npm run build。