PM2 很多人以为只能管 Node.js,其实它本质上是一个进程管理器。只要是能在命令行启动的长期运行程序,PM2 都可以托管,比如 Node.js、Rust 编译出来的二进制、Go 服务、Python 脚本、Shell 脚本等。

例如一个 Rust 后端服务,可以这样启动:

pm2 start ./target/release/gateway \
    --name bazar-api \
    --cwd /var/www/bazar_api \
    --update-env

这篇整理一下 PM2 的常用命令、参数含义和部署时经常会用到的操作。

安装

PM2 通常通过 npm 安装:

npm install -g pm2

查看版本:

pm2 -v

如果服务器上没有 Node.js 环境,需要先安装 Node.js。即使你的服务不是 Node 写的,PM2 自己仍然依赖 Node 运行。

启动服务

最基本的启动方式:

pm2 start app.js

指定进程名:

pm2 start app.js --name my-api

启动二进制文件:

pm2 start ./target/release/gateway --name bazar-api

启动时传递参数给应用:

pm2 start ./server --name my-server -- --port 8080 --host 0.0.0.0

注意 -- 后面的内容会传给你的应用,而不是传给 PM2。

例如:

pm2 start ./target/release/gateway \
    --name bazar-api \
    --cwd /var/www/bazar_api \
    --update-env

这条命令的含义是:

  • pm2 start ./target/release/gateway:启动当前项目里的 gateway 二进制。
  • --name bazar-api:PM2 中显示的进程名叫 bazar-api,后续可以用这个名字重启、停止、看日志。
  • --cwd /var/www/bazar_api:把工作目录切到 /var/www/bazar_api 后再启动程序。
  • --update-env:使用当前 shell 中最新的环境变量更新 PM2 进程环境。

--cwd 对后端服务很重要。很多程序会读取相对路径文件,例如 .envconfig.tomldata/app.dbstatic/uploads/。如果工作目录不对,程序可能能启动,但会读错配置或找不到文件。

查看进程

查看所有 PM2 进程:

pm2 list

或者:

pm2 status

常见字段:

  • name:进程名。
  • id:PM2 内部进程 ID。
  • mode:fork 或 cluster。
  • pid:系统进程 ID。
  • status:online、stopped、errored 等。
  • restart:重启次数。
  • cpu / mem:CPU 和内存占用。

查看某个进程详情:

pm2 show bazar-api

或者:

pm2 describe bazar-api

这里可以看到启动命令、工作目录、日志路径、环境变量、重启次数等信息。排查“为什么服务启动后行为不对”时很有用。

日志

查看所有进程日志:

pm2 logs

查看指定进程日志:

pm2 logs bazar-api

只看最近 100 行:

pm2 logs bazar-api --lines 100

清空 PM2 日志:

pm2 flush

查看日志文件路径:

pm2 show bazar-api

PM2 默认把日志放在:

~/.pm2/logs/

常见会有两个文件:

  • bazar-api-out.log:标准输出。
  • bazar-api-error.log:标准错误。

如果服务启动失败,第一步通常就是:

pm2 logs bazar-api --lines 200

重启、停止、删除

重启指定服务:

pm2 restart bazar-api

停止指定服务:

pm2 stop bazar-api

重新启动已经停止的服务:

pm2 start bazar-api

删除指定服务:

pm2 delete bazar-api

重启所有服务:

pm2 restart all

停止所有服务:

pm2 stop all

删除所有服务:

pm2 delete all

stopdelete 的区别:

  • stop:只是停止,进程还在 PM2 列表里。
  • delete:从 PM2 列表中移除这个进程。

更新环境变量

PM2 启动进程后,会保存当时的环境变量。之后你修改了 .env 或 shell 里的环境变量,直接 pm2 restart 不一定会生效。

更新环境变量时用:

pm2 restart bazar-api --update-env

或者启动时:

pm2 start ./target/release/gateway \
    --name bazar-api \
    --cwd /var/www/bazar_api \
    --update-env

如果你的服务依赖这些变量,建议重启时固定加上:

pm2 restart bazar-api --update-env

不过要注意:--update-env 更新的是 PM2 进程环境,不等于自动读取 .env 文件。是否读取 .env,取决于你的程序自己有没有加载 .env。例如 Rust 后端常见做法是用 dotenvy 或配置模块在启动时读取。

指定环境变量启动

可以在命令前直接写环境变量:

APP_ENV=production PORT=8080 pm2 start ./target/release/gateway --name bazar-api

也可以配合 --update-env

APP_ENV=production PORT=8080 pm2 start ./target/release/gateway \
    --name bazar-api \
    --cwd /var/www/bazar_api \
    --update-env

如果环境变量很多,建议用 ecosystem 配置文件,不要在命令行里堆太长。

开机自启

PM2 管理的服务,如果服务器重启后也要自动恢复,需要配置 startup。

生成开机自启命令:

pm2 startup

PM2 会输出一条带 sudo 的命令,复制执行。

然后保存当前进程列表:

pm2 save

以后服务器重启时,PM2 会恢复这次保存的进程列表。

常见流程:

pm2 start ./target/release/gateway --name bazar-api --cwd /var/www/bazar_api
pm2 save
pm2 startup

如果你新增、删除、改名了 PM2 进程,记得重新:

pm2 save

否则服务器重启后恢复的还是旧列表。

查看已保存的 dump:

pm2 resurrect

pm2 resurrect 会按保存的进程列表恢复服务。正常情况下 systemd 会自动调用它。

使用 ecosystem 配置文件

命令行适合简单服务,但生产环境更推荐写 ecosystem.config.js

示例:

module.exports = {
  apps: [
    {
      name: "bazar-api",
      script: "./target/release/gateway",
      cwd: "/var/www/bazar_api",
      exec_mode: "fork",
      instances: 1,
      autorestart: true,
      max_memory_restart: "500M",
      env: {
        APP_ENV: "production",
        PORT: "8080",
      },
    },
  ],
};

启动:

pm2 start ecosystem.config.js

重启并更新环境:

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

只启动配置里的某一个应用:

pm2 start ecosystem.config.js --only bazar-api

配置文件的好处:

  • 启动参数可版本管理。
  • 不容易忘记 cwd、环境变量、内存限制。
  • 多个服务可以统一管理。
  • 部署脚本更短、更稳定。

Node.js 的 cluster 模式

PM2 对 Node.js 有 cluster 模式,可以启动多个实例利用多核 CPU:

pm2 start app.js -i max

指定 4 个实例:

pm2 start app.js -i 4

ecosystem 写法:

module.exports = {
  apps: [
    {
      name: "node-api",
      script: "app.js",
      exec_mode: "cluster",
      instances: "max",
    },
  ],
};

注意:cluster 模式主要适合 Node.js HTTP 服务。Rust、Go 这类二进制服务通常用 fork 模式即可。如果想多实例部署 Rust/Go 服务,一般会在应用端、端口分配、Nginx upstream、systemd 或容器编排层面处理。

监听文件变化自动重启

开发环境可以使用 watch:

pm2 start app.js --watch

指定忽略目录:

pm2 start app.js --watch --ignore-watch="node_modules logs"

生产环境一般不建议随便开 --watch。如果日志、上传文件、缓存目录频繁变化,可能导致服务反复重启。

内存超限自动重启

限制内存,超过后自动重启:

pm2 start app.js --max-memory-restart 500M

ecosystem:

module.exports = {
  apps: [
    {
      name: "api",
      script: "app.js",
      max_memory_restart: "500M",
    },
  ],
};

这适合防止服务内存泄漏把机器拖垮,但它不是根治方案。如果服务频繁因为内存限制重启,还是要看日志和监控找原因。

监控

终端监控界面:

pm2 monit

查看进程资源占用:

pm2 list

查看详细信息:

pm2 show bazar-api

PM2 也有付费的 PM2 Plus / PM2 Enterprise,但一般小型项目只用本地命令就够了。

常见部署流程

以 Rust 服务为例,常见部署流程是:

cd /var/www/bazar_api
git pull
cargo build --release
pm2 restart bazar-api --update-env

如果是第一次部署:

cd /var/www/bazar_api
cargo build --release
pm2 start ./target/release/gateway \
    --name bazar-api \
    --cwd /var/www/bazar_api \
    --update-env
pm2 save

如果使用 ecosystem:

cd /var/www/bazar_api
cargo build --release
pm2 start ecosystem.config.js
pm2 save

以后更新:

cd /var/www/bazar_api
git pull
cargo build --release
pm2 restart ecosystem.config.js --update-env
pm2 save

常见问题

服务启动后找不到配置文件

先看工作目录:

pm2 show bazar-api

重点看 exec cwd。如果不对,重新指定:

pm2 delete bazar-api
pm2 start ./target/release/gateway \
    --name bazar-api \
    --cwd /var/www/bazar_api \
    --update-env

修改环境变量后不生效

使用:

pm2 restart bazar-api --update-env

如果还是不生效,确认程序是否真的读取了 .env,以及 .env 是否在正确的 cwd 下。

服务一直重启

查看日志:

pm2 logs bazar-api --lines 200

查看重启次数:

pm2 list

常见原因:

  • 程序启动即崩溃。
  • 端口被占用。
  • 数据库连不上。
  • 配置文件路径不对。
  • 权限不足,无法读取文件或写入目录。
  • 环境变量缺失。

服务器重启后服务没起来

确认是否保存了进程列表:

pm2 save

确认是否配置了开机自启:

pm2 startup

确认当前用户是否正确。PM2 的进程列表是按用户隔离的。你用 root 启动的 PM2,和用 www-data 或普通用户启动的 PM2,不是同一套列表。

端口被占用

查看日志通常能看到 address already in use

可以用:

lsof -i :8080

找到占用端口的进程后再决定是否停止它。

常用命令速查

命令作用
pm2 start app.js --name api启动并命名进程
pm2 start ./server --name api --cwd /path/app指定工作目录启动
pm2 list查看进程列表
pm2 status查看进程状态
pm2 show api查看进程详情
pm2 logs api查看指定进程日志
pm2 logs api --lines 100查看最近 100 行日志
pm2 restart api重启进程
pm2 restart api --update-env重启并更新环境变量
pm2 stop api停止进程
pm2 delete api删除进程
pm2 restart all重启全部进程
pm2 flush清空日志
pm2 monit打开监控界面
pm2 startup生成开机自启配置命令
pm2 save保存当前进程列表
pm2 resurrect恢复保存的进程列表

总结

PM2 最常用的能力其实就几件事:启动、命名、指定工作目录、看日志、重启、保存开机自启。

生产环境里,建议至少做到这几点:

  • 每个服务都用 --name 命名。
  • 后端服务尽量显式指定 --cwd
  • 修改环境变量后使用 --update-env
  • 第一次部署成功后执行 pm2 save
  • 复杂项目使用 ecosystem.config.js 管理启动参数。
  • 出问题先看 pm2 logs <name> --lines 200pm2 show <name>

对非 Node.js 服务来说,PM2 不是唯一选择,systemd、Docker、supervisord 都能做类似的事。但如果你想要一个简单、命令友好、日志查看方便的进程管理工具,PM2 依然很实用。