Skip to content

快速入门:跑通你的第一个应用 ​

定位:动手课。跟着敲一遍,20 分钟内获得"我已经会日常使用 PM2"的手感。
前置:一台 Linux 机器,已装 Node.js(建议 LTS),已读 核心概念

安装 PM2 ​

PM2 是 npm 包,装法本质都是“全局装一次,得到同一个 pm2 命令”。任选一种即可,默认推荐方式一(npm)。前三种方式都要求本机已有 Node.js(PM2 7.x 需 Node ≥ 18)。

方式一:npm(最通用、默认推荐) ​

bash
npm install -g pm2        # 全局安装

方式二:yarn ​

bash
yarn global add pm2

仅 Yarn 1.x(Classic)可用;Yarn 2+(Berry)已移除 yarn global 命令,用 Berry 时请退回 npm / pnpm。

方式三:pnpm ​

bash
pnpm add -g pm2

若装完提示 pm2: command not found,多半是 pnpm 的全局 bin 目录不在 PATH:执行 pnpm bin -g 查看该目录,把它加进 PATH 即可。

方式四:apt(Debian/Ubuntu 的官方 .deb)——版本滞后,仅特殊场景 ​

先破除一个常见误区:Debian/Ubuntu 的官方软件源里并没有 pm2 这个包,直接 apt install pm2 会报 Unable to locate package pm2。官方文档提供的 Debian/Ubuntu 装法,是先用它的安装脚本添加 PM2 官方 apt 仓库(脚本会顺带装 Node LTS):

bash
sudo apt update && sudo apt install -y curl
curl -sL https://raw.githubusercontent.com/Unitech/pm2/master/packager/setup.deb.sh | sudo -E bash -
# 脚本结束会提示把当前用户加入 pm2 组——重新登录一次后再使用 pm2

⚠️ 不推荐日常/生产使用:PM2 这个官方 apt 仓库(packagecloud 的 Keymetrics/pm2)已多年不更新(撰写时最新仍是 3.2.x,而 npm 上已是 7.x),远落后于本文 5.x–7.x 的叙述范围,与新版 Node 的兼容性也无保证;脚本本身还依赖 apt-key 等过时做法。只有“必须用 .deb 做系统级管理、或环境禁止访问 npm 源”时才考虑。不想要时可 sudo apt remove pm2,再回到 npm 安装。

任选一种装完后,验证一下:

bash
pm2 -v                    # 验证版本(如 7.x.x,依所装版本而定)

npm 全局目录没有写权限时会报 EACCES,处置见 故障排查与最佳实践;生产环境建议用普通用户安装、避免用 root 跑应用。以后升级 PM2 后记得执行一次 pm2 update(见 命令速查)。

安装后第一次执行任意 pm2 命令(如 pm2 ls),会自动在后台启动 daemon:

bash
pm2 ls
# 首次输出类似:
# ┌──────┬────┬─────────┬─────────┬─────┬────────┬──────────┐
# │ name │ id │ mode    │ status  │ ↺   │ cpu    │ memory   │
# └──────┴────┴─────────┴─────────┴─────┴────────┴──────────┘

看到一张空表格 = daemon 已就绪。可以用 pm2 ping 确认 daemon 存活。

写一个"待托管"的应用 ​

新建 app.js,一个极简 HTTP 服务(后面所有演示都用它):

js
// app.js —— 一个简单的可观测服务
const http = require('http');

const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
  res.end(`hello from pid=${process.pid} time=${new Date().toISOString()}\n`);
});

// 故意周期性打印一些日志,方便观察日志功能
setInterval(() => console.log('tick', new Date().toISOString()), 5000);

server.listen(3000, () => console.log('listening on 3000, pid=' + process.pid));

直接验证它能跑:

bash
node app.js &            # 前台/后台跑一下
curl http://127.0.0.1:3000   # 应返回 hello from pid=...
kill %1                  # 或 Ctrl+C,关掉手工进程

交给 PM2 托管 ​

bash
pm2 start app.js --name demo

输出一张表格,重点看这几列:

列含义
idPM2 分配的进程编号(从 0 开始)
name应用名,这里是 demo
modefork(或 cluster,见 集群模式与零停机发布)
↺重启次数(restarts)
status应为 online
cpu / memory实时资源占用

验证服务真的在跑,并且跟你的终端无关:

bash
curl http://127.0.0.1:3000
# hello from pid=12345 ...

# 把当前 shell 关掉/退出登录,再开一个新终端:
pm2 ls          # demo 依然 online
curl http://127.0.0.1:3000   # 依然有响应 —— 这就是"守护"的意义

观察:日志与监控 ​

bash
pm2 logs demo        # 实时跟随 demo 的输出(console.log / console.error)
# 每 5 秒能看到一行 tick ...;Ctrl+C 退出查看(进程不受影响)

pm2 logs demo --lines 100     # 回看最近 100 行
pm2 logs demo --err           # 只看错误输出

pm2 monit          # 全屏监控面板:实时 CPU/内存/日志(按 q 退出)

日志的落盘位置、时间戳、轮转等详见 日志与轮转。

做一次"崩溃演习" ​

体会 PM2 的自动重启。给进程发个致命的未捕获异常信号:

bash
# 让 demo 进程崩溃:给它发 SIGKILL(模拟 OOM 被杀 / 进程崩溃)
pm2 pid demo        # 拿到 PID
kill -9 $(pm2 pid demo)

sleep 1
pm2 ls
# 你会看到 demo 依然 online,但 ↺(重启次数)变成了 1 —— 它被自动拉起来了
curl http://127.0.0.1:3000   # 服务"没断"

结论:异常退出 → 自动重启。这也是"应用为什么莫名其妙重启过 N 次"的答案——去查 ↺ 列和重启策略(监控与告警)。

日常管理五件套 ​

bash
pm2 restart demo     # 重启:先停旧进程再起新进程(有短暂中断)
pm2 stop demo        # 停止:进程退出,但记录仍在列表里(status=stopped)
pm2 start demo       # 把已 stop 的进程再次启动(不是重复加一条!)
pm2 delete demo      # 彻底删除:停止并从列表移除,日志文件保留在磁盘

# 想顺带改参数可以:
pm2 restart demo --update-env    # 重启并重新加载当前 shell 的环境变量
pm2 restart demo --time          # 之后日志自动带时间戳

记笔记:

  • stop 是"暂停",delete 是"删除"。新手最容易把 delete 当 stop 用。
  • pm2 restart 是"杀旧起新";想少中断请用 reload(仅 cluster,见 集群模式与零停机发布)。
  • 命令都可以用名字或 id:pm2 restart demo 与 pm2 restart 0 等价。

用配置文件代替手敲参数 ​

刚才所有选项都是命令行传的。进程一多、参数一长,就该写配置文件了。把上面过程变成声明式:

js
// ecosystem.config.js
module.exports = {
  apps: [
    {
      name: 'demo',
      script: 'app.js',
      instances: 1,          // 1 个实例
      exec_mode: 'fork',     // fork 模式
      max_memory_restart: '200M', // 内存超过 200M 自动重启(见 06)
      time: true,            // 日志行自动加时间戳(另一种写法:log_date_format 自定义格式,见 05)
      env: {
        NODE_ENV: 'development',
      },
      env_production: {
        NODE_ENV: 'production',
      },
    },
  ],
};
bash
pm2 start ecosystem.config.js              # 用默认 env 启动
pm2 start ecosystem.config.js --env production   # 注入 env_production 并启动
pm2 delete all                             # 清掉本次演示的所有进程

注意:日志时间戳相关配置(time / log_date_format)的取舍详见 日志与轮转;其余字段详解见 配置文件(先照抄即可)。

配置文件(.js 或 .json/.cjs)里能配置的东西非常多,字段逐个详解见 配置文件。

生产收尾:保存 + 开机自启 ​

bash
pm2 save        # 把当前进程清单存为快照(dump.pm2)
pm2 startup     # 按输出提示,把那条 sudo 命令执行一遍(注册 systemd 单元)

原理与细节(包括如何卸载自启)在 开机自启与远程部署。

本课小结:你已会的 vs 待学 ​

已掌握下一步去学
安装、start / ls / logs / monit命令全集 → 命令速查
restart / stop / delete、崩溃演习重启策略细节 → 监控与告警
配置文件 + --env字段详解 → 配置文件
save / startupsystemd 原理与部署 → 开机自启与远程部署
fork 模式单实例多核与零停机 → 集群模式与零停机发布

参考链接 ​