PM2 + Nginx 部署 Node 服务前,先跑完这份检查
Node 服务上线不是 git pull && pm2 restart 就结束。容易出问题的是端口没监听、Nginx 还指旧端口、环境变量漏了、日志没落盘、回滚包找不到。
下面用一个 Express 服务举例,假设进程名叫 codenest,本机端口是 3000,公网由 Nginx 反代。
1. 上线前先确认工作区干净
git status --short
git rev-parse --short HEAD
如果不是 Git 部署,也要有等价版本号。没有版本号,出了问题很难说清楚线上跑的是哪份代码。
不要把 .env、pem、数据库文件、上传目录打进提交:
git status --short --ignored | head -80
git check-ignore -v .env || echo '.env is not ignored'
看到 .env is not ignored 就先停下来修 .gitignore。
2. 本地先跑语法和启动检查
Node 没有统一编译步骤,至少可以做语法检查:
node --check server.js
如果项目拆了多个 JS 文件:
find services public -name '*.js' -print0 | xargs -0 -n1 node --check
注意:public 里的浏览器脚本如果用了 document,node --check 只做语法解析,不会执行,不影响。
启动一次本地服务:
PORT=3000 npm start
另开终端验证:
curl -fsS http://127.0.0.1:3000/health
没有健康检查就补一个。上线时需要一个不依赖登录、不改数据、能快速返回的探针。
3. 上线前备份运行期数据
SQLite 示例:
stamp=$(date +%Y%m%d-%H%M%S)
mkdir -p data/backups
sqlite3 data/blog.db ".backup 'data/backups/blog-$stamp.sqlite'"
sqlite3 data/backups/blog-$stamp.sqlite 'pragma integrity_check;'
上传目录:
tar -czf data/backups/uploads-$stamp.tar.gz uploads
tar -tzf data/backups/uploads-$stamp.tar.gz >/dev/null
备份命令失败就停下。代码能回滚,用户上传文件丢了不一定能补回来。
4. 检查环境变量
只检查变量是否存在,不打印密钥值:
node - <<'NODE'
require('dotenv').config();
const required = [
'APP_BASE_URL',
'SESSION_SECRET',
'GITHUB_CLIENT_ID',
'GITHUB_CLIENT_SECRET',
'GITHUB_CALLBACK_URL'
];
const missing = required.filter((name) => !process.env[name]);
if (missing.length) {
console.error('missing env:', missing.join(', '));
process.exit(1);
}
console.log('required env ok');
NODE
不要在日志里输出 SESSION_SECRET、OAuth secret、API key。排障时只输出“存在/不存在”和地址类非敏感字段。
5. PM2 重载前看状态
pm2 status
pm2 describe codenest
pm2 logs codenest --lines 40
重点看:
- 进程是不是 online。
- restart 次数有没有异常增长。
- 错误日志里有没有已经存在的报错。
如果上线前日志已经在报错,先处理旧问题,不要把新版本叠上去。
6. Nginx 配置先做语法检查
sudo nginx -t
如果改过站点配置,再看反代端口:
sudo nginx -T 2>/dev/null | grep -n "proxy_pass\|server_name\|listen"
确认 proxy_pass 指向服务真实监听端口,比如:
proxy_pass http://127.0.0.1:3000;
Nginx 配置不通过时不要 reload。
7. 执行发布
常见顺序:
git pull --ff-only
npm ci --omit=dev
pm2 reload codenest --update-env
如果不是 Git 部署,把第一步换成你的解包或同步命令。关键是不要在同一次发布里混入不清楚来源的手工文件。
npm ci 比 npm install 更适合部署,因为它按 lockfile 安装,依赖结果更可预期。
8. 发布后立刻验证本机和公网
本机:
curl -fsS http://127.0.0.1:3000/health
公网:
curl -I https://example.com/health
curl -I https://example.com/
把 example.com 换成你的域名。
看日志:
pm2 logs codenest --lines 80
tail -n 80 data/logs/app.log
tail -n 80 data/logs/error.log
检查点:
/health本机和公网都返回 200。- 首页至少返回 200 或预期重定向。
- PM2 restart 次数没有快速上涨。
error.log没有新错误刷屏。
9. 回滚命令提前写好
回滚不要现场想。至少写清楚上一个版本和恢复数据的位置。
Git 回滚示例:
git log --oneline -5
git checkout <上一版commit>
npm ci --omit=dev
pm2 reload codenest --update-env
curl -fsS http://127.0.0.1:3000/health
如果这次发布包含数据库迁移,要提前写明:
- 是否允许代码回滚但数据不回滚。
- 是否有反向迁移脚本。
- 哪些后台任务需要暂停。
没想清楚这些,不要把“可回滚”写进发布单。
10. 最小发布清单
每次上线前后把这段跑完:
git status --short
node --check server.js
sqlite3 data/blog.db ".backup 'data/backups/pre-release.sqlite'"
sqlite3 data/backups/pre-release.sqlite 'pragma integrity_check;'
sudo nginx -t
pm2 status
pm2 reload codenest --update-env
curl -fsS http://127.0.0.1:3000/health
tail -n 80 data/logs/error.log
如果其中任何一步失败,处理失败原因后再走下一步。发布流程最怕“上了再说”。
还没有评论,欢迎先发第一条。