PM2简介:

PM2是一个守护进程管理器,它将帮助您管理和保持应用程序在线。

PM2官网地址: https://pm2.keymetrics.io/docs/usage/quick-start/

PM2的优点:

  1. 支持进程行为配置 ,即可以通过配置,实现对pm2管理应用的一些基础属性更新修改,如应用名称,启动模式等;
  2. 支持集群模式,支持负载均衡,但因采用nodejs的cluster模块实现,仅适用于nodejs进程;
  3. 支持source map,此项针对js, source map文件是js源文件的信息文件,里面存储着源文件的位置信息;
  4. 支持热重启;
  5. 支持部署工作流,pm2可依据测试环境和线上环境自动部署到不同的服务器,同时运行在不同配置下;
  6. 支持监听重启,在文件更新等情况下可实现进程自动重启;
  7. 日志管理,两种日志,pm2系统日志与管理的进程日志,默认会把进程的控制台输出记录到日志中;
  8. 监控功能,pm2 monit监控cpu和memory使用情况,keymetrics监控更为详细;
  9. 支持pm2模块开发,实现pm2的功能扩展, 比如美团团队开发的pm2.5
  10. 最大内存重启,设置最大内存限制,超过限制自动重启;

第1步-安装Node.js

首先,使用NodeSource软件包归档文件安装最新的LTS版本的Node.js。

要安装NodeSource PPA并访问其内容,您首先需要更新软件包索引并安装curl:

apt update
apt install curl

确保您位于主目录中,然后使用curl来获取Node.js 10 .x归档文件的安装脚本:

cd ~
curl -sL https://deb.nodesource.com/setup_10.x -o nodesource_setup.sh

您可以使用nano或您喜欢的文本编辑器检查此脚本的内容:

nano nodesource_setup.sh

检查完脚本后,请在sudo下运行它:

bash nodesource_setup.sh

PPA将添加到您的配置中,并且本地软件包缓存将自动更新。从Nodesource运行安装脚本后,可以安装Node.js软件包:

apt install nodejs

要检查在完成这些初始步骤后已安装的Node.js版本,请输入:

nodejs -v
Outputv10.16.0

nodejs软件包包含nodejs二进制文件以及npm(用于Node模块的软件包管理器),因此您无需单独安装npm。

npm使用主目录中的配置文件来跟踪更新。它将在您第一次运行npm时创建。执行以下命令以验证是否已安装npm并创建配置文件:

npm -v
Output6.9.0

如果显示npm未安装,那就使用下面命令安装npm

apt update
apt install nodejs npm

为了使某些npm软件包起作用(例如,那些需要从源代码编译代码的软件包),您将需要安装build-essential软件包:

apt install build-essential

现在,您具有必要的工具来处理需要从源代码编译代码的npm软件包。

步骤2 —安装PM2

接下来,我们安装PM2,它是Node.js应用程序的流程管理器。 PM2可以守护应用程序,以便它们作为服务在后台运行。

使用npm在服务器上安装最新版本的PM2:

npm install pm2 -g

-g选项告诉npm在全球范围内安装该模块,因此它在系统范围内都可用。

首先让我们使用pm2 start命令在后台运行hello.js应用程序:

pm2 start hello.js

这还将您的应用程序添加到PM2的进程列表中,该列表在您每次启动应用程序时都会输出:

Output[PM2] Spawning PM2 daemon with pm2_home=/home/sammy/.pm2
[PM2] PM2 Successfully daemonized
[PM2] Starting /home/sammy/hello.js in fork_mode (1 instance)
[PM2] Done.
┌──────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────┬───────────┬───────┬──────────┐
│ App name │ id │ mode │ pid  │ status │ restart │ uptime │ cpu │ mem       │ user  │ watching │
├──────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────┼───────────┼───────┼──────────┤
│ hello    │ 0  │ fork │ 1338 │ online │ 0       │ 0s     │ 0%  │ 23.0 MB   │ sammy │ disabled │
└──────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────┴───────────┴───────┴──────────┘
 Use `pm2 show <id|name>` to get more details about an app

如您所见,PM2会根据文件名(不带.js扩展名)以及PM2 id来自动分配应用名称。 PM2还维护其他信息,例如进程的PID,其当前状态和内存使用情况。

如果PM2下运行的应用程序崩溃或被杀死,它将自动重新启动,但是我们可以采取额外的步骤,使用startup子命令使该应用程序在系统启动时启动。此子命令生成并配置启动脚本,以在服务器启动时启动PM2及其托管进程。输入以下内容:

pm2 startup

您将看到如下所示的输出,描述了PM2生成的服务配置:

Output[PM2] Init System found: systemd
Platform systemd
Template
[Unit]
Description=PM2 process manager
Documentation=https://pm2.keymetrics.io/
After=network.target

[Service]
Type=forking
User=root
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
Environment=PM2_HOME=/root/.pm2
PIDFile=/root/.pm2/pm2.pid
Restart=on-failure

ExecStart=/usr/lib/node_modules/pm2/bin/pm2 resurrect
ExecReload=/usr/lib/node_modules/pm2/bin/pm2 reload all
ExecStop=/usr/lib/node_modules/pm2/bin/pm2 kill

[Install]
WantedBy=multi-user.target

Target path
/etc/systemd/system/pm2-root.service
Command list
[ 'systemctl enable pm2-root' ]
[PM2] Writing init configuration in /etc/systemd/system/pm2-root.service
[PM2] Making script booting at startup...
[PM2] [-] Executing: systemctl enable pm2-root...
Created symlink /etc/systemd/system/multi-user.target.wants/pm2-root.service → /etc/systemd/system/pm2-root.service.
[PM2] [v] Command successfully executed.
+---------------------------------------+
[PM2] Freeze a process list on reboot via:
$ pm2 save

[PM2] Remove init script via:
$ pm2 unstartup systemd

现在,您已经创建了一个在引导时运行pm2的systemd单元。该pm2实例依次运行hello.js。

使用systemctl启动服务:

systemctl start pm2-root.service

检查系统单元的状态:

systemctl status pm2-root.service

您应该看到如下输出:

Output● pm2-root.service - PM2 process manager
   Loaded: loaded (/etc/systemd/system/pm2-root.service; enabled; vendor preset: enabled)
   Active: active (running) since Fri 2019-07-12 16:09:54 UTC; 4s ago

有关systemd的详细概述,请参阅Systemd Essentials:使用服务,单元和日志。

除了我们已经介绍的内容之外,PM2还提供了许多子命令,这些子命令使您可以管理或查找有关应用程序的信息。

使用以下命令停止应用程序(指定PM2 App名称或ID):

pm2 stop app_name_or_id

重新启动应用程序:

pm2 restart app_name_or_id

列出当前由PM2管理的应用程序:

pm2 list

使用其应用名称获取有关特定应用的信息:

pm2 info app_name

可以使用monit子命令拉起PM2过程监视器。这将显示应用程序状态,CPU和内存使用情况:

pm2 monit

请注意,不带任何参数运行pm2还将显示一个带有示例用法的帮助页面。

PM2常用命令:

  1. pm2 start <script_file|config_file> [options] 启动指定应用,如pm2 start index.js --name httpServer;
  2. pm2 stop <appName> [options] 停止指定应用,如pm2 stop httpServer;
  3. pm2 list 把所有pm2启动实例列举出来,注意:pm2 stop 某个项目后,该项目还会存在pm2 list 的列表里面, 只是状态是 stop, 要想去掉该项目,用pm2 delete
  4. pm2 reload|restart <appName> [options] 重启指定应用,如pm2 restart httpServer;
  5. pm2 show <appName> [options] 显示指定应用详情,如pm2 show httpServer;
  6. pm2 delete <appName> [options] 删除指定应用,如pm2 delete httpServer,如果修改应用配置行为,最好先删除应用后,重新启动方才生效,如修改脚本入口文件;
  7. pm2 kill 杀掉pm2管理的所有进程;
  8. pm2 logs <appName> 查看指定应用的日志,即标准输出和标准错误;
  9. pm2 monit 监控各个应用进程cpu和memory使用情况;
  10. pm2 startOrReload <appName> 如果项目没有启动就执行 start 如果项目正在运行 就执行relaod

提示 除了使用 appName 之外, 还可以使用 all: 全部程序 id: 该程序的 id

PM2配置方式:

1.CLI方式(命令行方式)

下面是使用命令行方式启动的示例

pm2 start pm2.json --name appName 
--watch true--max-memory-restart 500M 

启动可以附加的参数包括不限于下面这些:

--script   启动脚本路径

--instances应用启动实例个数,仅在cluster模式有效,默认为fork;

--exec_mode应用启动模式,支持fork和cluster模式;

--name     指定 app 名字

--watch    监听重启,启用情况下,文件夹或子文件夹下变化应用自动重启

--ignore_watch  忽略监听的文件夹,支持正则表达式,配合 watch 使用

--max-memory-restart  最大内存限制数,超出自动重启;

--env      环境变量,`object类型,如{"NODE_ENV":"production",<span> </span>"ID":<span> </span>"42"`};

--log      指定 log 的位置, 若要指定新位置,需将原本的 process 刪掉,再重新启动即可

--output   指定 output log 位址

--error    指定 error log 位址

--log-date-format     指定日志日期格式,如YYYY-MM-DD HH:mm:ss;

--arg1 --arg2 --arg3  额外的参数

--restart-delay   自动重启时,要 delay 多久

--autorestart     默认为`true`, 发生异常的情况下自动重启

--cron_restart    crontab时间格式重启应用,目前只支持cluster模式;

--restart_delay   异常重启情况下,延时重启时间;

2.配置文件方式

可以是 json文件 比如名字叫做 pm2.json 如下 (注意 json里面是不能有注释的,我下面是为了方便解释说明):

{

`  ``"apps"``: [{`

`    ``"name"``:<span> </span>``"shark-pro"``,`

`    ``"script"``:<span> </span>``"server/www.js"``,`

`    ``"cwd"``:<span> </span>``""``,`

`    ``"exec_mode"``:<span> </span>``"cluster"``,`

`    ``"instances"``: 0,`

`    ``"max_memory_restart"``:<span> </span>``"1G"``,`

`    ``"autorestart"``:<span> </span>``true``,`

`    ``"node_args"``: [],`

`    ``"args"``: [],`

`    ``"env"``: {`

`      ``"NODE_ENV"``:<span> </span>``"production"`

`    ``}`

`  ``}],`

`  ``"deploy"``: {`

`    ``"production"``: {`

`      ``"user"``:<span> </span>``"root"``,`

`      ``// 支持多个 host 部署`

`      ``"host"``: [``"host1"``,<span> </span>``"host2"``],`

`      ``// 要部署的分支`

`      ``"ref"``:<span> </span>``"origin/master"``,`

`      ``// Git 仓库地址`

`      ``"repo"``:<span> </span>``"git@gitlab.com:user/yourProject.git"``,`

`      ``// 要部署到 server 上的文件路径`

`      ``"path"``:<span> </span>``"/var/www/yourProjectName"``,`

`      ``// 如果 ssh 有设定好,从 local 连接到 remote 端将不会再询问是否将 remote 端的 public key 加到 known host`

`      ``"ssh_options"``:<span> </span>``"StrictHostKeyChecking=no"``,`

`      ``// 在 pm2 要从 local 端连到 remote 端之前要执行的指令,可以多個指令,由 ; 分割,也可以指定 shell script 的路径`

`      ``"pre-setup"``:<span> </span>``"apt update -y; apt install git -y"``,`

`      ``// 当 pm2 在 remote 机器上把代码 clone 下來之后会执行的指令,同上,可以多個指令,由 ; 分割,也可以指定 shell script 的路径`

`      ``"post-setup"``:<span> </span>``"ls -la"``,`

`      ``// 当 pm2 在 local 要连上 remote 部署之前 ,在 local 端所要执行的指令, 同上,可以多個指令,由 ; 分割,也可以指定 shell script 路径`

`      ``"pre-deploy-local"` `:<span> </span>``"echo 'This is a local executed command'"``,`

`      ``// 部署完成后, 所要執行的指令 同上,可以多個指令,由 ; 分割,也可以指定 shell script 的路径`

`      ``"post-deploy"``:<span> </span>``"npm i && pm2 startOrRestart pm2.json --env production"``,`

`      ``"env_production"``: {`

`          ``"NODE_ENV"``:<span> </span>``"production"`

`      ``}`

`    ``}`

`  ``}`

`}`

也可以是 .yaml文件 比如名字叫 ecosystem.yaml 文件, 如下:

apps:

  `- script: server/www.js`

    `name:  myApp`

    `env:`

      `COMMON_VARIABLE:<span> </span>`true

    `env_production:`

      `NODE_ENV: production`

deploy:

  `production:`

    `user: root`

    `host:`

      `- 12.12.12.12`

    `port:<span> </span>`'12'

    `ref`: origin/master

    `repo: git@github.com:xxxxxxx.git`

    `path: /root/www/deploy/production`

    `ssh_options: StrictHostKeyChecking=no`

    `pre-deploy: git fetch --all`

    `post-deploy:<span> </span>`'npm i && pm2 startOrRestart ecosystem.yaml --env production'

    `env:`

      `NODE_ENV: production`

常见问题:

如下是执行 pm2 list 把运行的项目罗列出来

QQ截图20220211032158.png

status就是pm2 的启动模式, pm2 有两种启动模式 fork cluster

1. fork 与 cluster 启动模式

fork模式,单实例多进程,常用于多语言混编,比如php、python等,不支持端口复用,需要自己做应用的端口分配和负载均衡的子进程业务代码。
缺点就是单服务器实例容易由于异常会导致服务器实例崩溃。

cluster模式,多实例多进程,但是只支持node,端口可以复用,不需要额外的端口配置,0代码实现负载均衡。
优点就是由于多实例机制,可以保证服务器的容错性,就算出现异常也不会使多个服务器实例同时崩溃。

2. reload 与 restart 区别

restart 是杀死并重新启动进程。

<span>reload 与 </span>restart相反,reload实现0秒的停机重新加载

也就说说 使用reload,pm2逐个重新启动所有进程,始终保持至少一个进程运行。
如果 reload 重新加载系统没有成功地重新加载应用程序,则超时将回退到经典的重新启动即 restart。

最后修改:2022 年 02 月 15 日 04 : 10 AM