常见部署报错排查手册
2026 年 09 月 23 日 · 约 8 分钟读完
部署报错看着吓人,其实翻来覆去就那么几类。这篇是排查手册,不是教程:先养成一个习惯——报错信息原文完整记下来(截图或复制),再动手。很多报错的第一行就写了原因,跳过它直接搜偏方,是新人最常见的弯路。
浏览器打不开网站:按这三层查
- 域名解析:ping 一下域名,看返回的 IP 是不是你的服务器。刚改的解析要等几分钟到几小时
- 安全组端口:云厂商控制台看 80/443 放行了没有。这是最常见的,新人十个有八个卡在这
- 服务本身:在服务器上 curl 一下 localhost 看应用到底起没起来。起不来就往下看
Node 版本不对
报错里出现 engines、EBADENGINE,或者莫名其妙的语法错误,先看项目要求的 Node 版本(交付包的说明里会写,一般还有 .nvmrc 文件)。用 nvm 装对应版本再试。不要在服务器上装一个「最新版」就以为万事大吉,大版本不一样,跑不起来是常态。
数据库连不上
先看 DATABASE_URL 写对了没有,格式是固定的:
postgresql://用户名:密码@地址:5432/数据库名然后确认三件事:数据库服务在跑、用户名密码对、npx prisma generate 跑过(没跑会报 client 没生成的错)。密码里有特殊字符的,记得做 URL 编码,@ 写成 %40,# 写成 %23,这个坑很隐蔽。
构建时内存不足被杀掉
1G 内存的小鸡跑 npm run build,中途没动静然后进程没了,基本就是内存不够被系统杀了。应急办法是加 swap:
# 加 2G 交换分区,应急用
fallocate -l 2G /swapfile && chmod 600 /swapfile && mkswap /swapfile && swapon /swapfile长期办法是在本地构建好再上传产物,或者换 2G 内存的机器。构建慢和构建被杀是两回事,慢可以等,被杀必须加内存。
502 Bad Gateway
502 的意思是反向代理(Nginx/Caddy)没找到后面的应用。查两样:代理配置里写的端口,和应用实际监听的端口是不是同一个;应用进程还在不在。十有八九是应用崩了没起来,或者端口写错了。
日志在哪看
报错信息不够用的时候,直接看日志,答案基本都在里面。你怎么起的服务,就去哪看:pm2 起的看 pm2 logs,systemd 起的看 journalctl,docker 起的看 docker logs。看最近的几十行,从下往上找第一个 ERROR。
终极办法:把报错贴给 AI
EazyOPC 交付包里有一段排查提示词,复制给 Claude Code 或 Codex,再贴上完整的报错原文、你做到哪一步了、服务器是什么系统,让它帮你看。给 AI 的信息越全,它定位得越准;只贴半截报错,它也只能猜。
npm install 卡住或报错
卡住不动超过五分钟,基本是网络问题:服务器在海外,npm 官方源慢或者被墙。换国内镜像源,一条命令的事。报错先看第一行:EACCES 是权限问题,别用 sudo npm,用普通用户装 node;版本冲突看报错里提到的包名。终极办法:删掉 node_modules 和 package-lock.json 重新装。重装之前先确认 node 版本对,不然白重装。
npm config set registry https://registry.npmmirror.com
rm -rf node_modules package-lock.json && npm install端口被占用:EADDRINUSE
启动时报 EADDRINUSE 或者 port already in use,意思是这个端口已经有程序在听了。两种可能:你之前起的网站没关,或者别的程序占了。用 lsof 查是谁,确认是自己之前的进程就 kill 掉,或者换个端口。还有一种常见情况:pm2 里同名起了两个实例,自己跟自己打架,pm2 list 看到重复的删掉一个。
lsof -i :3000
kill 进程号
pm2 list时区不对:定时任务总在奇怪的时间跑
服务器默认是 UTC 时间,你的备份 cron 写的是「凌晨 3 点」,实际跑的是 UTC 3 点,也就是北京时间上午 11 点——正好是用户活跃的时候,备份拖慢网站。先 date 看一眼服务器现在几点,对不上就设时区。Node 程序里涉及到时间的,也可以在环境变量里加 TZ。以后日志里的时间戳对不上,先看时区,十有八九是它。
date
timedatectl set-timezone Asia/ShanghaiHTTPS 证书过期了
浏览器突然报证书过期,先别慌。certbot 申请的证书 90 天有效,靠定时任务自动续,如果定时任务没配好就会过期。先手动续一次,续上了再去查定时任务为什么没跑。用 Caddy 的话一般不用操心,它会自动续,但前提是 80 端口能从外网访问到——安全组里 80 端口被关了,续期就会失败。续完之后浏览器硬刷新一下,缓存的旧页面会骗你。
certbot renew
# 模拟续期,测试定时任务能不能跑通
certbot renew --dry-run构建成功,页面却一片空白
npm run build 过了,网站能打开但页面空白,这种最气人。先看浏览器控制台的报错:红字会告诉你是哪个请求失败了。常见原因就两个:环境变量没配(API 地址是空的,页面调不到数据),或者前后端地址写错了(调了 localhost,线上当然没有)。对照着一项项查,八成是环境变量的问题。
数据库迁移报错
prisma db push 或者 migrate 报错,先看报错说的表存不存在:「表已存在」多半是之前 push 过一半,手动连上数据库看看表到底建没建。拿不准的时候,先备份数据,再删了重建。记住顺序:备份第一,动手第二。数据库相关的操作,没有「撤销」按钮。
最后说个习惯:每次排查完,把「报错现象—原因—解决办法」记三行。半年下来就是你自己的排查手册,比什么教程都管用,因为上面的每一条都是你真金白银踩出来的。下次再遇到,三秒钟定位,不用从头查起。
git pull 冲突:服务器上别改代码
部署时 git pull 报冲突,说明有人在服务器上直接改过代码。规矩:服务器上永远别改代码,改代码在本地,提交了再拉。已经改了怎么办?改动要保留就先提交,不重要的直接 git stash 或 git reset 扔掉。最干净的做法:部署用全新 clone,旧目录整个删掉,杜绝一切「服务器上多一行没提交的代码」。
权限问题:EACCES
报错里有 EACCES、permission denied,别第一反应 sudo。sudo npm 装的东西,属主是 root,以后普通用户跑就处处报错。正确做法:node 用普通用户装(nvm 装到用户目录),项目文件都属于这个用户。已经搞乱的,用 chown 把项目目录的属主改回来。记住:权限问题靠「理顺属主」解决,不靠 sudo 硬来,sudo 只会把坑埋得更深。
构建时内存爆了:heap out of memory
npm run build 跑到一半报 JavaScript heap out of memory,是 Node 默认堆内存不够。临时加大再构建:
NODE_OPTIONS=--max-old-space-size=1536 npm run build1536 是给 2G 内存的机器用的,1G 的机器改成 768 再加 swap。这只是让构建通过,治标;治本是换大内存,或者本地构建好传产物上去。构建通过不代表跑得动,运行时内存也要留够,别把机器压到 100%。
CORS 报错:跨域
浏览器控制台报 CORS、Access-Control-Allow-Origin,意思是前端调了另一个域名的接口,浏览器不让。本地开发没事、一上线就报错,经典。本质是前后端地址不一致:最省事的办法是让反向代理把 API 和页面转到同一个域名下,就没有跨域了。非要跨域,就在后端配好允许的域名,别图省事配成星号,支付相关的接口配星号等于裸奔。
环境变量改了没生效
改了 .env,网站还是老样子,两个原因:一是没重启,环境变量是启动时读一次,改完必须重启进程;二是用 pm2 起的,pm2 会缓存环境变量,重启要用 pm2 restart --update-env。验证办法:重启后打一条日志把关键变量(脱敏的)打印出来,确认读到的是新的。别靠「我觉得生效了」,靠日志确认。
域名解析不生效
A 记录改了,ping 还是老 IP:先看 TTL,多久生效看它;再看是不是本地 DNS 缓存,换个网络或用手机流量试试;用 dig 域名 看返回的 IP 是不是新的,dig 绕开本地缓存看权威结果。刚改完几分钟不生效太正常了,喝杯水再看。超过几小时还不生效,再去检查记录是不是加错了地方(比如加到了别的域名下)。