PM2 Node.js 进程管理方案
PM2 的安装、进程管理、集群模式、日志轮转、零停机重载与开机自启,附 ecosystem 配置模板。
安装与基础使用
#Node.js 进程上生产后需要守护:崩溃自动重启、日志轮转、多核利用、零停机更新。PM2 一条命令覆盖这些,另带监控面板和开机自启。
# 全局安装
npm install -g pm2
# 验证版本
pm2 --version
# 启动一个 Node.js 应用
pm2 start app.js
pm2 start app.js --name my-api # 指定进程名称
pm2 start app.js -i max # 以集群模式启动,使用所有 CPU 核心
pm2 start app.js -- --port=3001 # 向应用传递参数
常用命令速查
## 进程管理
pm2 list # 查看所有进程状态
pm2 show my-api # 查看单个进程的详细信息
pm2 logs # 实时查看所有日志
pm2 logs my-api # 查看指定进程日志
pm2 monit # 终端监控面板(CPU / 内存实时曲线)
# 生命周期
pm2 restart my-api # 重启
pm2 reload my-api # 零停机重载(集群模式)
pm2 stop my-api # 停止
pm2 delete my-api # 从 PM2 列表中移除
# 批量操作
pm2 restart all # 重启所有进程
pm2 stop all # 停止所有进程
pm2 delete all # 清空所有进程
零停机重载 vs 重启
| 操作 | 行为 | 适用场景 |
|---|---|---|
restart | 杀死进程 → 启动新进程(有短暂停机) | 单实例、开发环境 |
reload | 逐个 worker 重启,始终保持至少一个在线 | 生产环境集群模式 |
gracefulReload | 等待现有请求处理完毕再重启 | 长连接、WebSocket |
日志管理
# 查看日志
pm2 logs --lines 200 # 显示最近 200 行
pm2 logs my-api --err # 只看错误日志
pm2 flush # 清空所有日志
# 日志轮转(内置模块)
pm2 install pm2-logrotate
# 配置轮转参数
pm2 set pm2-logrotate:max_size 50M # 单文件上限
pm2 set pm2-logrotate:retain 7 # 保留最近 7 个归档
pm2 set pm2-logrotate:compress true # 归档后 gzip 压缩
Ecosystem 配置文件
#正式项目用 ecosystem.config.js 替代命令行参数,提交到版本库。
module.exports = {
apps: [{
name: 'api-server',
script: 'dist/main.js',
instances: 'max',
exec_mode: 'cluster',
env: {
NODE_ENV: 'production',
PORT: 3000,
},
env_development: {
NODE_ENV: 'development',
PORT: 3001,
watch: ['src'],
watch_delay: 1000,
ignore_watch: ['node_modules', 'dist', 'logs'],
},
// 错误处理
max_restarts: 10,
restart_delay: 5000,
min_uptime: '30s',
// 日志
error_file: './logs/err.log',
out_file: './logs/out.log',
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
merge_logs: true,
// 优雅退出
kill_timeout: 5000,
listen_timeout: 3000,
// 健康检查
max_memory_restart: '500M',
}],
}
启动时选择环境:
pm2 start ecosystem.config.js # 默认使用 env
pm2 start ecosystem.config.js --env development # 使用 env_development
集群模式
#Node.js 单线程,一台机器有多少核就起多少 worker 才用得满。
instances: 'max', // 自动检测 CPU 核心数
instances: 4, // 手动指定数量
instances: 0, // 与 max 相同
reload 的执行流程:
worker 1 ########.... <- 正在服务的连接
worker 2 ########....
worker 3 ########....
worker 4 ########....
pm2 reload api-server
worker 1 ########.... <- 正在关闭
worker 2 ............ <- 已启动新版
worker 3 ########.... <- 正在关闭
worker 4 ............ <- 已启动新版
逐个替换 worker,全程至少有一个在响应请求。
开机自启
## 生成系统自启脚本
pm2 startup
# 保存当前进程列表(重启后自动恢复)
pm2 save
# 查看已保存的进程
pm2 resurrect
pm2 startup 自动检测初始化系统(systemd / launchd / rc.d)并生成对应脚本。
部署:搭配 Git 的远程部署
#PM2 内置 deploy,从 Git 拉代码并自动重启。
module.exports = {
apps: [{
name: 'api',
script: 'dist/main.js',
}],
deploy: {
production: {
user: 'deploy',
host: ['192.168.1.100'],
ref: 'origin/main',
repo: 'git@github.com:user/project.git',
path: '/opt/app/api',
'pre-deploy': 'git fetch --all',
'post-deploy': 'pnpm install && pnpm build && pm2 reload ecosystem.config.js',
'pre-setup': 'echo "Starting deployment..."',
},
},
}
# 首次部署
pm2 deploy production setup
# 后续更新
pm2 deploy production
监控与告警
## 终端监控面板
pm2 monit
# 基于 Keymetrics 的 Web 仪表盘(免费额度足够个人项目)
pm2 link <secret> <public-key>
# 自定义指标(在应用代码中)
const io = require('@pm2/io')
io.counter('requests/min').inc()
io.meter('req_rate').mark()
io.histogram('response_time').update(duration)
要接 Prometheus + Grafana 或自建告警,可用 pm2 describe 加日志系统对接外部监控。
常见问题
#内存泄漏自动重启
max_memory_restart: '500M', // 达到 500MB 时自动重启
日志时间戳缺失
ecosystem.config.js 里要设 log_date_format,否则日志只有原始文本没有时间。
端口占用
# 找出占用端口的进程
lsof -i :3000
# 或
ss -tlnp | grep 3000
kill -9 <PID>
PM2 命令找不到
# 检查全局 node_modules 路径是否正确
npm root -g
# 如果指向非预期目录,设置 N_PREFIX 或重新安装 Node
pm2 与 systemd 的边界
PM2 本身也是进程。生产环境常见组合是 PM2 管应用、systemd 管 PM2:
# 方式一:让 systemd 直接管 Node(应用少时更简单)
# 参考上方 myapp.service 模板,Type=simple + Restart=on-failure
# 方式二:PM2 生成 systemd 自启单元(应用多时)
pm2 startup # 生成并启用 pm2.service
pm2 save
只有一两个 Node 服务 → 直接 systemd,少一层依赖;多服务、要集群和 pm2 reload → PM2 + pm2 startup。两者不要重复自启,systemd 和 pm2 同时托管会互相拉起。
重启频率过高保护
短时间内反复崩溃时 PM2 会自动停止尝试,避免 crash loop。由 max_restarts 和 restart_delay 控制:
max_restarts: 10, // min_uptime 窗口内最多重启次数
restart_delay: 5000, // 每次重启间隔 5 秒
min_uptime: '30s', // 运行满 30 秒才视为稳定,重置计数
总结
#起步三条:pm2 start + pm2 startup + pm2 save 管守护;instances: 'max' + exec_mode: 'cluster' 管多核;ecosystem.config.js + reload 管更新。直接复制上方配置,改 env 和项目名即可。