PM2 是 Node.js 生态中最常用的生产级进程管理器,但它的能力不止于"让 Node 脚本在后台跑起来"。本文从安装讲起,覆盖日常管理、集群、日志、监控、自启与生产部署的完整流程。


目录

  • 安装与基础概念
  • 启动与进程管理
  • ecosystem 配置文件
  • 集群模式(Cluster Mode)
  • 日志管理
  • 监控与指标
  • 开机自启
  • 零停机重载与发布
  • 内存与异常处理策略
  • 常见坑与排查
  • 速查表

安装与基础概念

# 全局安装
npm install -g pm2

# 或 pnpm
pnpm add -g pm2

PM2 的核心概念只有三个:

  • process:被 PM2 托管的一个应用实例
  • daemon:PM2 自身驻留后台的管理进程(~/.pm2/ 下保存状态)
  • ecosystem file:声明式配置文件(ecosystem.config.js),推荐的生产方式

验证安装:

pm2 -v
pm2 ping        # 检查 daemon 是否存活

启动与进程管理

启动一个应用

# 最简单的启动
pm2 start app.js

# 指定进程名(强烈建议,否则默认用文件名)
pm2 start app.js --name api-server

# 传递 Node 参数与应用参数
pm2 start app.js --name api --node-args="--max-old-space-size=2048" -- --port 3000

# 不限于 Node:任何可执行文件都可以托管
pm2 start python --name spider -- main.py
pm2 start ./worker.sh --name job

常用管理命令

pm2 list                    # 进程列表(别名 pm2 ls / pm2 status)
pm2 describe api-server     # 单个进程详情:路径、日志位置、重启次数、内存等
pm2 restart api-server      # 重启
pm2 reload api-server       # 优雅重载(集群模式下零停机)
pm2 stop api-server         # 停止(保留在列表中)
pm2 delete api-server       # 从 PM2 列表移除
pm2 save                    # 保存当前进程列表快照(供 resurrect / 自启恢复)

所有命令都可以用进程名、进程 id,或 all(全部进程)作为目标。

常用启动选项

选项作用
--name <n>指定进程名
-i <n> / --instances <n>实例数,max 表示按 CPU 核数
--watch文件变更自动重启(仅开发用)
--max-memory-restart 500M内存超限自动重启
--cron-restart "0 3 * * *"定时重启
--env KEY=VAL(ecosystem 中用)注入环境变量
--time日志加时间戳
--no-autorestart崩溃后不自动拉起

ecosystem 配置文件

生产环境不要靠 pm2 start 手敲参数,用 ecosystem.config.js 固化配置:

// ecosystem.config.js
module.exports = {
  apps: [
    {
      name: "api-server",
      script: "./dist/app.js",
      cwd: "/srv/myapp",
      instances: "max",           // 集群实例数
      exec_mode: "cluster",       // cluster | fork
      env: {
        NODE_ENV: "production",
        PORT: 3000,
      },
      // 内存与稳定性
      max_memory_restart: "512M",
      min_uptime: "10s",          // 启动不足 10s 就退出视为异常
      max_restarts: 10,           // 短时间内最多重启次数
      restart_delay: 3000,        // 每次重启间隔 ms
      // 日志
      out_file: "./logs/out.log",
      error_file: "./logs/err.log",
      merge_logs: true,
      time: true,
      // 优雅退出
      kill_timeout: 5000,         // SIGINT 后最多等 5s 再强杀
      listen_timeout: 8000,       // cluster 模式等待 listen 的超时
    },
    {
      name: "cron-job",
      script: "./jobs/daily.js",
      cron_restart: "0 4 * * *",  // 每天 4 点跑一次逻辑由应用自己控制
      autorestart: false,
    },
  ],
};

使用方式:

pm2 start ecosystem.config.js              # 启动全部
pm2 start ecosystem.config.js --only api-server
pm2 reload ecosystem.config.js             # 按配置重载
pm2 delete ecosystem.config.js             # 按配置移除

配置变更后需要 pm2 reload ecosystem.config.js 才会生效;只改环境变量可以配合 --update-env

pm2 reload ecosystem.config.js --update-env

集群模式(Cluster Mode)

Node 单进程只用一个核。exec_mode: "cluster" 让 PM2 基于 Node 的 cluster 模块启动多个实例,PM2 内置轮询负载均衡,多实例共享同一端口:

pm2 start app.js -i max           # 按 CPU 核数
pm2 start app.js -i 4             # 指定 4 个实例
pm2 scale api-server 8            # 运行中动态扩缩容

注意事项:

  • 有状态数据不能放进程内存(session、内存缓存、内存队列),要放 Redis / 数据库。
  • WebSocket 类应用需要考虑粘性会话(sticky session),通常交给前面的 Nginx / LB 处理,或用 Redis adapter。
  • 集群模式才支持真正的 reload 零停机;fork 模式的 reload 等价于 restart

日志管理

pm2 logs                    # 实时流式查看全部日志
pm2 logs api-server         # 指定进程
pm2 logs --lines 200        # 带历史行数
pm2 logs --err              # 只看错误日志
pm2 flush                   # 清空全部日志

默认日志在 ~/.pm2/logs/。生产环境建议:

  1. 应用自身用结构化日志库(pino / winston)输出,PM2 只负责兜底捕获 stdout/stderr。
  2. 安装 pm2-logrotate 做切割,避免日志撑爆磁盘:
pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 100M
pm2 set pm2-logrotate:retain 14
pm2 set pm2-logrotate:compress true
pm2 set pm2-logrotate:rotateInterval "0 0 * * *"

监控与指标

pm2 monit                   # 终端实时面板:CPU / 内存 / 重启次数
pm2 describe api-server     # 静态详情
pm2 plus                    # 连接 PM2 Plus(原 Keymetrics)在线面板,免费额度够用

采集自定义指标(供 pm2 monit 和 PM2 Plus 显示):

// 应用内
const io = require("@pm2/io");

const orderCounter = io.counter({ name: "orders_created" });
const onlineUsers = io.meter({ name: "online_users" });

orderCounter.inc();
onlineUsers.mark();

配合告警动作(内存超过阈值触发 webhook 等)可以用 @pm2/io 的 action / 阈值能力,或直接接 Prometheus:用 pm2-prometheus-exporter 暴露指标给 Prometheus + Grafana,这是自托管监控的主流方案。


开机自启

# 1. 生成当前用户的 systemd / launchd 启动脚本
pm2 startup
# 按提示复制执行它输出的命令(需要 sudo)

# 2. 保存当前进程列表
pm2 save

之后机器重启,PM2 daemon 会拉起 pm2 save 快照里的所有进程。

注意:

  • pm2 startup 之后再新增的进程,必须重新 pm2 save 才会加入自启列表。
  • 取消自启:pm2 unstartup
  • 服务器上如果以非 root 用户运行应用,startup 时要用 pm2 startup systemd -u <user> --hp /home/<user> 指定用户,否则权限和 ~/.pm2 路径会对不上。

零停机重载与发布

reload 的流程:逐实例启动新进程 → 新进程 listen 成功 → 旧进程收到 SIGINT → 旧进程清理完毕退出。应用端需要配合两件事:

// 1. 处理 SIGINT,优雅关闭
process.on("SIGINT", async () => {
  server.close();                 // 停止接新连接
  await db.disconnect();          // 释放数据库连接等资源
  process.exit(0);
});

// 2. 用 ready 信号告知 PM2 "我已就绪"(需配置 wait_ready: true)
//    listen 成功后:
if (process.send) process.send("ready");

ecosystem 中对应配置:

wait_ready: true,
listen_timeout: 8000,
kill_timeout: 5000,

典型发布流程:

cd /srv/myapp
git pull
pnpm install --prod
pnpm build
pm2 reload ecosystem.config.js --update-env   # 零停机

PM2 也内置了 pm2 deploy(基于 SSH 的部署机),但现在一般用 CI/CD(GitHub Actions / GitLab CI)跑上面的脚本替代。


内存与异常处理策略

生产进程一定会遇到内存泄漏和随机崩溃,PM2 的价值就在这里:

{
  max_memory_restart: "512M",   // 内存超限重启,兜底内存泄漏
  min_uptime: "10s",            // 启动 10s 内就挂 = 启动失败
  max_restarts: 10,             // 1 分钟内重启 10 次后放弃,避免死循环重启
  restart_delay: 3000,          // 退避重启
  autorestart: true,
}

排障三板斧:

pm2 describe <name>    # 看 unstable restarts / 最近退出码
pm2 logs <name> --err --lines 100
pm2 report             # 生成诊断报告(含 daemon 状态)

常见坑与排查

1. pm2 startup 后重启机器进程没起来 多半是没有重新 pm2 save,或 startup 时用户不一致导致读的是另一个 ~/.pm2/dump.pm2

2. 集群模式下应用启动报 EADDRINUSE fork 模式误当 cluster 用,或应用自己手动监听了端口冲突逻辑。cluster 模式下只需正常 listen(port),由 PM2 共享端口。

3. 日志没有内容 应用用了 daemonize / fork 后台化(比如某些 Python 框架的 --daemon),PM2 捕获不到输出。去掉应用自身的后台化,把前台运行交给 PM2。

4. --watch 在线上把服务打挂 watch 只适合开发。生产用 CI 触发 reload

5. 环境变量不生效 reload 不会自动刷新 env,要加 --update-env.env 文件建议在应用内用 dotenv 加载,而不是依赖 PM2。

6. dump.pm2 损坏导致 daemon 起不来

pm2 kill
rm -rf ~/.pm2/dump.pm2
pm2 resurrect   # 或重新 pm2 start ecosystem.config.js && pm2 save

速查表

场景命令
启动pm2 start ecosystem.config.js
列表pm2 ls
详情pm2 describe <name>
日志pm2 logs <name> --lines 100
重启pm2 restart <name>
零停机重载pm2 reload <name>
扩缩容pm2 scale <name> 4
监控面板pm2 monit
保存快照pm2 save
开机自启pm2 startup + pm2 save
清空全部pm2 delete all / pm2 kill(杀 daemon)
升级 PM2 后刷新 daemonpm2 update

一句话总结:本地 pm2 start 随便玩,生产一律 ecosystem 文件 + cluster 模式 + pm2 save + logrotate,这四件事做完,PM2 才算真正"管好"了你的进程。