pm2 是使用 node.js 开发的进程管理器,实现统一方式管理进程,如:崩溃后拉起、启动/停止、监控、日志管理等。
安装
npm install pm2@latest -g
为什么要全局(global)方式安装 pm2?
pm2 被设计成管理用户的全部应用,pm2 的数据保存在 ~/.pm2 目录下,同一用户只能启动一个 pm2 后台进程(PM2 daemon),不同用户的 pm2 互不影响。不安装为全局的情况下,如果安装多个版本的 pm2,不同版本的 pm2 前端工具程序与 pm2 后台进程(PM2 daemon)交互是有风险的。
应用管理
启动应用
pm2 start -n app1 app1.js pm2 start -n app2 app2.js
列出应用
pm2 list
应用详情
pm2 describe app1
停止应用
pm2 stop app1 pm2 stop app2
删除应用
pm2 delete app1 pm2 delete app2
开机启动
应用启动后需要保存,应用才会在开机后由 pm2 服务启动。
pm2 save
创建 pm2 系统服务,开机启动 pm2
sudo pm2 startup systemd -u app
不重启试运行一下,看是否正常
# 清空进程并退出 pm2,回到干净的系统状态 sudo systemctl stop pm2 ps aux | grep node # 启动 pm2 服务,验证一下应用是否正常启动 sudo systemctl start pm2 pm2 list
日志管理
《 pm2的日志管理 》有详细描述。
多 node.js 版本共存
pm2 本身就是 node.js 开发的程序,依赖 node.js,pm2 应用可以使用不同版本的 node.js。
pm2 命令行工具会通过“#!/usr/bin/env node”方式引用 node,如果应用也以同样的方式引用 node.js,就要随时注意切换 node.js 版本,一不小心 pm2 命令行工具和 pm2 应用使用的 node.js 版本会错乱,有一定风险性。一个 node.js 版本安装的模块不能保证与另一个 node.js 版本兼容,特别是一些 c++ 扩展模块。
我以前的实践中,应用会提供一个环境脚本 .bashrc ,在操作某个应用时,总是会通过 source .bashrc
先设置应用的 shell 环境变量,通过 $PATH 环境变量指定 node 命令为应用所需的 node.js 版本不是一个好主意,当操作 pm2 时,pm2 也会使用这个应用的 node.js 版本。
从这一点上看,不应该使用 node.js 、php、python、ruby 之类的脚本语言来开发进程管理器,它本身的依赖管理就是个大麻烦,使用 go、c 或 c++ 来开发会好得多。
理想情况下,pm2 和 应用(app)总是使用正确的 node.js 版本,可以归为以下三种情形。新应用应该总是假设布署环境为情形 1,不要过多考虑系统运行的 node.js 版本,这也就要求应用能够兼容各种 node.js 版本,但是现实情况是,node.js 以及 javascript 发展得太快了,应用依赖的各种 node.js 模块也往往做不到兼容各种 node.js 版本,很多模块基于实现的简洁性考虑,提供多个版本分别对应不同的 node.js 版本,导致应用也必须从一开始就选择特定的 node.js 版本,不同团队、人员及项目跟进新技术步调不一致时,情形 2 及情形 3 是现实的选择。
情形 1:系统中只有一个 node.js 版本,并且是全局安装
在专机专用的生产环境下,这种情形会很常见,特别是 docker 容器环境下。
这是最简单的一种情况,不需要为 node.js 版本操心,整个开发组织在 node.js 版本选择上共进退,保持一致。
情形 2:系统中有一个全局 node.js 版本,应用有自已的 node.js 版本
开发环境下,或者同一机器部署大量微服务的情况下,一般就是这种情形。
这是最复杂的一种情况,在运行应用代码的时候,要确保切到应用所需的 node.js 版本,在执行 pm2 操作的时候,要确保切到 pm2 所需的 node.js 版本,有如履薄冰的感觉。
node.js 版本需要在以下方面正确匹配:
pm2 的 node.js 版本
pm2 本身就是一套用户全局的进程管理工具,使用全局的 node.js 版本是自然而然的选择。
否则就一定要记得使用正确的 node.js 版本运行 pm2:/usr/local/node-v5.0.0/bin/node pm2 list,很是不便。
应用的 node.js 版本
建议使用
--interpreter
选项指定 node.js 版本,参见讨论:Using different versions of node via nvm for each app · Issue #1034 · Unitech/pm2 。警告:pm2 在
cluster
模式下,--interpreter
选项被忽略,详见:Module version mismatch 错误排查 | 看看俺 – KanKanAn.com 。这是最关键的一点,应用的 node.js 版本不对,可能导致应用启动失败,中断服务。
应用的辅助脚本的 node.js 版本
使用 node.js 开发的应用附带命令行工具运行时如果 node.js 版本不对,通常不会对运行中的服务造成影响。
可以简单地写一些 shell 脚本封装,在 shell 脚本中指定正确的 node.js 版本,如:
dump.sh
#!/bin/bash /usr/local/node-v5.0.0/bin/node ./dump.js
也可以直接在 node.js 脚本中引用正确的 node.js 版本,如:
dump.js
#!/usr/local/node-v5.0.0/bin/node var fs = require('fs'); ...
chmod a+x dump.js ./dump.js
情形 3:系统没有全局 node.js 版本,应用各自维护 node.js 版本
这是上面情况的简化版,考验开发、运维团队的纪律性。
由于 $PATH 中没有 node.js,不会由于没有指定 node.js 绝对路径无意间引用错误的 node.js 版本。
可以把 node.js 安装在应用根目录下,如下目录结构所示:
Applications | | |--- Application 1 | | | |--------- node | | | |--------- package.json | | | |--------- ... | | |--- Application 2 | | | |--------- node | | | |--------- package.json | | | |--------- ... | | |--- Application 3 | | | |--------- node | | | |--------- package.json | | | |--------- ... |
甚至 pm2 也通过以上方式安装自已的 node.js 版本。
通过 ./node/bin/node 引用 node.js 可执行程序,不要试图通过将 ./node/bin 目录加到 $PATH 中以简化使用,否则操作不同应用或 pm2 时,又会一不小心引用到错误的 node.js 版本。