PM2详解
零、文章目录
一、简介
- PM2 是一个
守护进程管理器
,它将帮助您管理和保持您的应用程序在线。 - PM2 入门很简单,它以简单直观的 CLI 形式提供,可通过 NPM 安装。
- 官网地址:https://pm2.keymetrics.io/
二、安装
1、安装
$ npm install pm2@latest -g
# or
$ yarn global add pm2
2、查看版本
$ pm2 -v
3、程序目录
- 安装完成之后,日志等信息都会在用户目录下生成
4、更新 PM2
-
更新 PM2 速度极快(不到几秒)且无缝。
-
安装最新的 PM2 版本:
$ npm install pm2 -g
- 更新内存中的 PM2 守护进程
$ pm2 update
5、更新Node.js
- 升级 Node.js 安装时,需要更新PM2中Node.js 版本。
$ pm2 unstartup
$ pm2 startup
三、管理进程
1、开始
(1)启动应用程序
$ pm2 start app.js
- 您还可以启动任何类型的应用程序,如 bash 命令、脚本、二进制文件:
$ pm2 start "npm run start"
$ pm2 start "ls -la"
$ pm2 start app.py
(2)启动并显示日志流
- 要启动应用程序并显示日志流,使用
--attach
选项 - 通过 Ctrl-C 退出时,该应用程序仍将在后台运行。
$ pm2 start app.js --attach
(3)传递参数
--
之后传递的所有选项都将作为参数传递给应用程序
$ pm2 start app.js -- arg1 arg2
(4)配置文件
- 当同时管理多个应用程序或必须指定多个选项时,可以使用配置文件。如下是 ecosystem.config.js 文件的示例:
module.exports = {
apps : [{
name : "limit worker",
script : "./worker.js",
args : "limit"
},{
name : "rotate worker",
script : "./worker.js",
args : "rotate"
}]
}
- 然后可以通过配置文件同时启动两个应用程序:
$ pm2 start ecosystem.config.js
2、重新开始
$ pm2 restart app_name # 重启应用
$ pm2 restart all # 重启所有应用
$ pm2 restart app1 app3 app4 # 重启多个应用
3、停止
- stop只会停止应用
$ pm2 stop app_name # 停止应用
$ pm2 stop [process_id] # 停止应用
$ pm2 stop all # 停止所有应用
$ pm2 stop app1 app3 app4 # 停止多个应用
4、删除
- delete停止和删除应用
$ pm2 delete app_name # 停止和删除应用
$ pm2 delete all # 停止和删除所有应用
5、列表
- 列出所有应用
$ pm2 list
# Or
$ pm2 [list|ls|l|status]
- 指定您希望应用程序列出的顺序
$ pm2 list --sort name:desc
# Or
$ pm2 list --sort [name|id|pid|memory|cpu|status|uptime][:asc|desc]
6、资源仪表板
- PM2 为您提供了一种监视应用程序资源使用情况的简单方法。
- Ctrl+C可以退出。
pm2 monit
7、显示应用详情
$ pm2 show app_name
8、重置重启计数
$ pm2 reset all
四、重启策略
- 当使用 PM2 启动应用程序时,应用程序会在自动退出、事件循环为空(node.js)或应用程序崩溃时自动重启。但您也可以配置额外的重启策略,例如:
- 在指定的 CRON 时间重启应用
- 文件更改后重新启动应用程序
- 当应用程序达到内存阈值时重新启动
- 延迟启动和自动重启
- 默认情况下崩溃或退出时禁用自动重启(应用程序始终使用 PM2 重启)
- 在特定的指数增长时间自动重启应用程序
1、cron 时间重启
$ pm2 start app.js --cron-restart="0 0 * * *"
# Or when restarting an app
$ pm2 restart app --cron-restart="0 0 * * *"
- 通过配置文件,使用
cron_restart
属性:
module.exports = {
apps : [{
name: 'Business News Watcher',
script: 'app.js',
instances: 1,
cron_restart: '0 0 * * *',
env: {
NODE_ENV: 'development'
},
env_production: {
NODE_ENV: 'production'
}
}]
}
- 要
禁用
cron 重启:
$ pm2 restart app --cron-restart 0
2、文件修改重启
- 当前目录或其子目录中的文件被修改时,PM2 可以自动重启您的应用程序。
- 如果应用程序以
--watch
选项启动,则stop停止应用程序不会阻止文件修改重启。要完全禁用文件修改重启功能,请执行以下操作:pm2 stop app --watch
。
$ pm2 start app.js --watch
- 通过配置文件,使用
watch: true
属性。
module.exports = {
script: "app.js",
watch: true
}
- 可以使用以下选项指定要
监视更改的文件夹
、忽略文件夹
和监视文件间隔
。
module.exports = {
script: "app.js",
// Specify which folder to watch
watch: ["server", "client"],
// Specify delay between watch interval
watch_delay: 1000,
// Specify which folder to ignore
ignore_watch : ["node_modules", "client/img"],
}
3、达到内存阈值重启
- PM2 在达到内存阈值后,允许进程自动重启。
- PM2 内部工作程序每 30 秒检查一次内存,因此可能不是立即触发重启。
- 单位可以是 K(ilobyte)(如
512K
)、M(egabyte)(如128M
)、G(igabyte)(如1G
)。
$ pm2 start app.js --max-memory-restart 300M
- 通过配置文件,使用
max_memory_restart
属性:
module.exports = {
script: 'app.js',
max_memory_restart: '300M'
}
4、重启延迟
- 使用
--restart-delay
选项设置自动重启的延迟时间
$ pm2 start app.js --restart-delay=3000
- 通过配置文件,使用
restart_delay
属性:
module.exports = {
script: 'app.js',
restart_delay: 3000
}
5、无自动重启
- 这在我们希望运行 1 次脚本并且不希望进程管理器在脚本完成运行时重新启动脚本的情况下很有用。
$ pm2 start app.js --no-autorestart
- 通过配置文件,使用
autorestart
属性:
module.exports = {
script: 'app.js',
autorestart: false
}
6、跳过退出代码重启
- 有时您可能希望应用程序在出现故障时自动重启(退出代码不等于0),而不希望进程管理器在正常关闭时重新启动它(退出代码等于 0)。
- 在这种情况下,可以设置
stop_exit_codes
选项以退出应该跳过自动重启的代码。
$ pm2 start app.js --stop-exit-codes 0
- 或者通过配置文件,使用
stop_exit_codes
属性:
module.exports = [{
script: 'app.js',
stop_exit_codes: [0]
}]
7、逐步增长重启延迟
- 当异常发生时(例如数据库关闭),设置
--exp-backoff-restart-delay
选项将逐步增长重启延迟的时间,而不是疯狂地重启应用。
$ pm2 start app.js --exp-backoff-restart-delay=100
- 通过配置文件,使用
exp_backoff_restart_delay
属性:
module.exports = {
script: 'app.js',
exp_backoff_restart_delay: 100
}
-
当设置
--exp-backoff-restart-delay
选项,且应用程序意外崩溃并时,您将能够看到一个新的应用程序状态waiting restart
。 -
通过运行
pm2 logs
你还会看到重启延迟增加。重启之间的重启延迟将以指数移动平均线增加,直到达到重启之间的最大值 15000 毫秒。当应用程序随后返回稳定模式时(正常运行时间不超过 30 秒),重启延迟将自动重置为 0 毫秒。
PM2 | App [throw:0] will restart in 100ms
PM2 | App [throw:0] exited with code [1] via signal [SIGINT]
PM2 | App [throw:0] will restart in 150ms
PM2 | App [throw:0] exited with code [1] via signal [SIGINT]
PM2 | App [throw:0] will restart in 225ms
五、输出日志
- 使用 PM2 启动应用程序后,您可以轻松查阅和管理日志。
- 日志文件位于文件夹中
$HOME/.pm2/logs
。
1、输出日志
$ pm2 logs
- 输出格式选项。
--json # json日志输出
--format # 格式化日志输出
--raw # 原始输出
--err # 仅显示错误输出
--out # 仅显示标准输出
--lines <n> # 输出最后N行,而不是默认情况下的最后15行
--timestamp [format] # 添加时间戳(默认格式YYYY-MM-DD-HH:MM:ss)
--nostream # 打印日志而不启动日志流
--highlight [value] # 突出显示给定值
-h, --help # 输出使用信息
- 一些重要的命令。
$ pm2 logs # 实时显示所有应用程序日志
$ pm2 logs app # 仅显示“app”应用程序日志
$ pm2 logs --json # 在json中显示新日志
$ pm2 logs app --lines 1000 #显示1000行app日志文件
- 使用资源仪表板检查日志。
$ pm2 monit
- 对于每个应用程序行,将打印此元数据。
{
"message": "echo\n", // 已被`console.log的实际消息`
"timestamp": "2017-02-06T14:51:38.896Z", // 消息的时间戳,可以格式化
"type": "out", // 日志类型,可以是`err`,`out`,`PM2`
"process_id": 0, // 应用进程ID
"app_name": "one-echo" // 应用名称
}
2、清空日志
$ pm2 flush # 清空日志
$ pm2 flush app # 清空app日志
3、日志选项
- 启动应用程序时,您可以指定许多选项,
pm2 start app.js [OPTIONS]
。
-l --log [path] # 指定文件路径以输出日志和错误日志
-o --output <path> # 指定日志文件
-e --error <path> # 指定错误日志文件
--time # 使用标准格式的时间戳为日志添加前缀
--log-date-format <format> # 使用自定义格式的时间戳为日志添加前缀
--merge-logs # 当运行具有相同应用程序名称的多个进程时,不要按id拆分文件
- 例如要为应用程序的日志添加前缀,您可以传递该选项
--time
:
$ pm2 start app.js --time
# Or a running app
$ pm2 restart app --time
- 例如在集群模式中的应用程序,当运行具有相同应用程序名称的多个进程时,不要按id拆分文件,可以使用
--merge-logs
选项。
$ pm2 start app.js --merge-logs
# Or a running app
$ pm2 restart app --merge-logs
4、配置文件
- 详见–七、配置文件–7、日志文件
5、滚动存储
pm2-logrotate
使用磁盘上的有限空间滚动存储日志。在此处阅读有关 pm2-logrotate 的更多信息。
$ pm2 install pm2-logrotate
- 设置本机 logrotate
sudo pm2 logrotate -u user
- 这将写入一个基本的配置,如下所示。
/home/user/.pm2/pm2.log /home/user/.pm2/logs/*.log {
rotate 12
weekly
missingok
notifempty
compress
delaycompress
create 0640 user user
}
六、持久应用
-
PM2 可以生成启动脚本并配置它们,以便在预期或意外的机器重启期间保持您的进程列表完整。PM2支持如下这些初始化系统
-
systemd: Ubuntu >= 16, CentOS >= 7, Arch, Debian >= 7
-
upstart: Ubuntu ==> 14
-
launchd: Darwin, MacOSx
-
openrc: Gentoo Linux, Arch Linux
-
rcd: FreeBSD
-
systemv: Centos 6, Amazon Linux
-
1、生成启动脚本
- 要自动生成和配置启动脚本,只需键入命令
pm2 startup
。
$ pm2 startup
[PM2] You have to run this command as root. Execute the following command:
sudo su -c "env PATH=$PATH:/home/unitech/.nvm/versions/node/v14.3/bin pm2 startup <distribution> -u <user> --hp <home-path>
- 然后将显示的命令复制/粘贴到终端执行,现在 PM2 会在开机时自动重启。
sudo su -c "env PATH=$PATH:/home/unitech/.nvm/versions/node/v14.3/bin pm2 startup <distribution> -u <user> --hp <home-path>
- 注意:您可以通过选项自定义服务名称
--service-name <name>
2、保存应用列表
- 启动所有需要的应用程序后,保存应用程序列表,以便在重启后重新生成。
$ pm2 save
3、手动复活进程
- 手动恢复以前保存的进程(通过 pm2 save)。
$ pm2 resurrect
4、禁用启动系统
- 要禁用和删除当前的启动配置:
pm2 unstartup
5、更新启动脚本
-
当您升级本地 Node.js 版本时,请务必更新 PM2 启动脚本,以便它运行您安装的最新 Node.js 二进制文件。
-
首先禁用并删除当前的启动配置(复制/粘贴该命令的输出)。
$ pm2 unstartup
- 然后恢复一个新的启动脚本。
$ pm2 startup
6、用户权限
- 假设您希望启动脚本在另一个用户下执行。只需更改
-u <username>
选项和--hp <user_home>
。
$ pm2 startup ubuntu -u www --hp /home/ubuntu
7、指定初始化系统
- 如果你愿意,你可以指定你自己使用的平台。
$ pm2 startup [ubuntu | ubuntu14 | ubuntu16 | ubuntu18 | ubuntu20 | ubuntu12 | centos | centos6 | arch | oracle | amazon | macos | darwin | freebsd | systemd | systemv | upstart | launchd | rcd | openrc]
8、Windows 启动脚本
- 要生成与 Windows 兼容的启动脚本,请查看pm2-installer
七、配置文件
- 在使用 PM2 管理多个应用程序时,可以使用一个
js/yaml/json
配置文件来组织它们。 - 几乎所有命令都可以在配置文件中使用
1、生成配置文件
- 要生成示例配置文件,您可以键入以下命令。
$ pm2 init simple
- 这将生成一个示例
ecosystem.config.js
。
module.exports = {
apps : [{
name : "app1",
script : "./app.js"
}]
}
- 如果您正在创建自己的配置文件,请确保它以
.config.js
结尾,以便 PM2 能够将其识别为配置文件。
2、作用于配置文件
- 您可以无缝地启动/停止/重新启动/删除配置文件中包含的
所有
应用程序。
# 启动所有应用
$ pm2 start ecosystem.config.js
# 停止所有应用
$ pm2 stop ecosystem.config.js
# 重启所有应用
$ pm2 restart ecosystem.config.js
# 重载所有应用
$ pm2 reload ecosystem.config.js
# 停止和删除所有应用
$ pm2 delete ecosystem.config.js
3、作用于特定应用
- 您还可以通过使用其名称和选项对特定应用程序进行操作
--only <app_name>
。 - 该
--only
选项也适用于启动/重新启动/停止/删除。
$ pm2 start ecosystem.config.js --only api-app
- 多个应用程序以逗号分隔。
$ pm2 start ecosystem.config.js --only "api-app,worker-app"
4、切换环境
- 您可以通过该选项指定不同的环境变量集
env_*
。
module.exports = {
apps : [{
name : "app1",
script : "./app.js",
env_production: {
NODE_ENV: "production"
},
env_development: {
NODE_ENV: "development"
}
}]
}
- 现在要在不同环境中的变量之间切换,请指定选项
--env [env name]
。
$ pm2 start process.json --env production
$ pm2 restart process.json --env development
5、常用属性
属性字段 | 类型 | 例子 | 描述 |
---|---|---|---|
name | (string) | “my-api” | 应用程序名称(默认为不带扩展名的脚本文件名) |
script | (string) | ”./api/app.js” | 相对于 pm2 start 的脚本路径 |
cwd | (string) | “/var/www/” | 您的应用程序将从中启动的目录 |
args | (string) | “-a 13 -b 12” | 包含通过 CLI 传递给脚本的所有参数的字符串 |
interpreter | (string) | “/usr/bin/python” | 解释器绝对路径(默认为节点) |
interpreter_args | (string) | ”–harmony” | 传递给口译员的选项 |
node_args | (string) | interpreter_args的别名 |
cwd:
如果要在脚本以外的位置维护配置文件(例如,/etc/pm2/conf.d/node-app.json
),您将需要设置cwd
属性。文件可以是相对于cwd
目录的,也可以是绝对的。
6、高级属性
属性字段 | 类型 | 例子 | 描述 |
---|---|---|---|
instances | number | -1 | 要启动的应用程序实例数 |
exec_mode | string | “cluster” | 启动应用程序的模式,可以是“cluster”或“fork”,默认fork |
watch | boolean or [] | true | 启用监视和重启功能,如果文件夹或子文件夹中的文件发生更改,您的应用程序将重新加载 |
ignore_watch | list | [”[/\]./”, “node_modules”] | 通过监视功能忽略某些文件或文件夹名称的正则表达式列表 |
max_memory_restart | string | “150M” | 如果超过指定的内存量,您的应用程序将重新启动。人性化格式:可以是“10M”、“100K”、“2G”等等…… |
env | object | {“NODE_ENV”: “development”, “ID”: “42”} | 将出现在您的应用程序中的环境变量 |
env_ | object | {“NODE_ENV”: “production”, “ID”: “89”} | 在执行 pm2 restart app.yml --env 时注入 |
source_map_support | boolean | true | 默认为真,[启用/禁用源映射文件] |
instance_var | string | “NODE_APP_INSTANCE” | 详见环境变量章节 |
filter_env | array of string | [ “REACT_” ] | 排除以“REACT_”开头的全局变量,不允许它们渗透到集群中。 |
-
"instances": 0
意味着 PM2 将根据 CPU 的数量启动最大可能的进程(集群模式)。 -
max_memory_restart
的值可以是。-
数字 例如
"max_memory_restart": 1024
表示 1024 字节(NOT BITS)。 -
String 因此,我们使其简短且易于配置:
G
,M
和K
,例如:"max_memory_restart": "1G"
表示 1 GB,"max_memory_restart": "5M"
表示 5 兆字节,"max_memory_restart": "10K"
表示 10 千字节(这些将转换为字节)。
-
-
--env <envname>
来告诉 pm2 使用进程文件中定义的特定环境。- 运行
pm2 start ecosystem.json
,它将使用默认环境启动您的应用程序。 - 运行
pm2 start ecosystem.json --env production
,它会使用production环境变量启动你的应用程序。
- 运行
{
"apps" : [{
"name" : "worker-app",
"script" : "./worker.js",
"watch" : true,
"env": {
"NODE_ENV": "development"
},
"env_production" : {
"NODE_ENV": "production"
}
},{
"name" : "api-app",
"script" : "./api.js",
"instances" : 4,
"exec_mode" : "cluster"
}]
}
7、日志文件
属性字段 | 类型 | 例子 | 描述 |
---|---|---|---|
log_date_format | (string) | “YYYY-MM-DD HH:mm Z” | 日志日期格式(见日志部分) |
error_file | (string) | 错误文件路径(默认为 $HOME/.pm2/logs/-error-.log) | |
out_file | (string) | 输出文件路径(默认为 $HOME/.pm2/logs/-out-.log) | |
log_file | (string) | 输出和错误日志的文件路径(默认禁用) | |
combine_logs | boolean | true | 如果设置为 true,避免使用进程 ID 为日志文件添加后缀 |
merge_logs | boolean | true | combine_logs 的别名 |
time | boolean | false | 默认为假。如果 true 自动为日志添加日期前缀 |
pid_file | (string) | pid 文件路径(默认为 $HOME/.pm2/pids/-.pid) |
- 通过设置
merge_logs: true
选项来禁用日志上的自动 ID 后缀。 - 例如要禁止将所有日志写入磁盘,您可以设置选项
out_file
和error_file
为/dev/null
或者NULL
(不依赖于平台,它们是硬编码的字符串)。
module.exports = {
apps : [{
name: 'Business News Watcher',
script: 'app.js',
instances: 1,
out_file: "/dev/null",
error_file: "/dev/null"
cron_restart: '0 0 * * *'
[...]
}]
}
8、控制属性
属性字段 | 类型 | 例子 | 描述 |
---|---|---|---|
min_uptime | (number) | 被视为已启动的应用程序的最短正常运行时间 | |
listen_timeout | number | 8000 | 如果应用程序没有监听,则强制重新加载之前的时间(以毫秒为单位) |
kill_timeout | number | 1600 | 发送最终 SIGKILL 之前的时间(以毫秒为单位) |
shutdown_with_message | boolean | false | 使用 process.send(‘shutdown’) 而不是 process.kill(pid, SIGINT) 关闭应用程序 |
wait_ready | boolean | false | 而不是重新加载等待监听事件,等待 process.send(‘ready’) |
max_restarts | number | 10 | 在您的应用程序被视为错误并停止重新启动之前,连续不稳定重新启动的次数(小于 1 秒间隔或通过 min_uptime 自定义时间) |
restart_delay | number | 4000 | 重新启动崩溃的应用程序之前等待的时间(以毫秒为单位)。默认为 0。 |
autorestart | boolean | false | 默认情况下为真。如果为 false,PM2 将不会在应用程序崩溃或和平结束时重新启动您的应用程序 |
cron_restart | string | “1 0 * * *” | 一个 cron 模式来重启你的应用程序。应用程序必须正在运行才能使 cron 功能正常工作 |
vizion | boolean | false | 默认情况下为真。如果为 false,PM2 将在没有 vizion 功能(版本控制元数据)的情况下启动 |
post_update | list | [“npm install”, “echo launching the app”] | 从 Keymetrics 仪表板执行拉取/升级操作后将执行的命令列表 |
force | boolean | true | 默认为假。如果为真,您可以多次启动同一个脚本,这通常是 PM2 不允许的 |
- min_uptime 的值可以是:
- 数字 例如
"min_uptime": 3000
表示 3000 毫秒。 - String 因此,我们使其简短且易于配置:
h
,m
和s
,例如:"min_uptime": "1h"
表示一小时,"min_uptime": "5m"
表示五分钟,"min_uptime": "10s"
表示十秒(这些将转换为毫秒)。
- 数字 例如
9、部署属性
属性字段 | 描述 | 类型 | 默认 |
---|---|---|---|
key | SSH key path | String | $HOME/.ssh |
user | SSH user | String | |
host | SSH host | [String] | |
ssh_options | SSH options with no command-line flag, see ‘man ssh’ | String or [String] | |
ref | GIT remote/branch | String | |
repo | GIT remote | String | |
path | path in the server | String | |
pre-setup | Pre-setup command or path to a script on your local machine | String | |
post-setup | Post-setup commands or path to a script on the host machine | String | |
pre-deploy-local | pre-deploy action | String | |
post-deploy | post-deploy action | String |
10、CLI/JSON 选项
- 所有键都可以在配置文件中使用,但在命令行上几乎保持相同,例如:
exec_mode -> --execute-command
max_restarts -> --max-restarts
force -> --force
- 可以在命令行传入变量,例如:
$ pm2 start test.js --node-args "port=3001 sitename='first pm2 app'"
- 该
nodeArgs
参数将被解析为
[
"port=3001",
"sitename=first pm2 app"
]
- 但不是
[
"port=3001",
"sitename='first",
"pm2",
"app'"
]
八、集群模式
-
集群模式允许联网的Node.js应用程序(http(s)/tcp/udp 服务器)在所有可用的 CPU 上扩展,无需任何代码修改。这极大地提高了应用程序的性能和可靠性,具体取决于可用的 CPU 数量。
-
在底层,这使用了 Node.js集群模块,以便扩展应用程序的子进程可以自动共享服务器端口。
1、启用集群模式
(1)命令启动
- 要启用
集群模式
,只需传递-i
选项 - -i或instances选项可以是
- 0/max将应用程序分布在所有 CPU 上
- -1将应用程序分布到所有 CPU - 1
- number将应用程序分布在number 个CPU上
$ pm2 start app.js -i max
(2)配置文件
- 需要将 exec_mode 设置为
cluster
,以便 PM2 在每个实例之间进行负载平衡。
module.exports = {
apps : [{
script : "api.js",
instances : "max",
exec_mode : "cluster"
}]
}
- 然后启动进程文件。
$ pm2 start processes.json
2、重新加载
restart
会终止并重新启动进程。reload
实现了0 秒停机时间
重新加载。- 如果
reload
未能重新加载您的应用程序,超时将回退到经典重启。
$ pm2 reload <app_name>
- 或者通过配置文件:
$ pm2 reload process.json
$ pm2 reload process.json --only api
3、优雅关机
-
在生产环境中,您可能需要等待处理完剩余的查询或关闭所有连接,然后再退出应用程序。
-
要优雅地关闭应用程序,您可以捕获SIGINT信号(PM2 退出时发送的第一个信号)并执行操作以等待/清除所有这些状态。
process.on('SIGINT', function() {
db.stop(function(err) {
process.exit(err ? 1 : 0);
});
});
4、无状态化
- 确保你的
应用程序是无状态的
,这意味着没有本地数据存储在进程中。 - 例如会话/websocket 连接、会话内存和相关的。使用 Redis、Mongo 或其他数据库在进程之间共享状态。
九、静态文件服务
- PM2 可以使用
pm2 serve
命令开启静态文件服务器。 - 它支持从指定文件夹提供原始文件,或者提供 SPA(单页应用程序)。
1、启动静态文件服务器
(1)命令启动
- 默认
<path>
为当前文件夹,默认端口为8080
。 - 您可以使用与普通应用程序相同的选项,例如
--name
或--watch
。
$ pm2 serve <path> <port>
(2)配置文件
- 在配置文件中环境变量中添加
PM2_SERVE_PATH
和PM2_SERVE_PORT
来指定路径和端口。
module.exports = {
script: "serve",
env: {
PM2_SERVE_PATH: '.',
PM2_SERVE_PORT: 8080
}
}
2、SPA单页应用程序
(1)命令启动
- 要自动将所有查询
重定向到 index.html
,请使用以下--spa
选项
$ pm2 serve --spa
(2)配置文件
- 在配置文件中设置静态文件服务器的
目录、端口、是否SPA启、重定向页面
。
module.exports = {
script: "serve",
env: {
PM2_SERVE_PATH: '.',
PM2_SERVE_PORT: 8080,
PM2_SERVE_SPA: 'true',
PM2_SERVE_HOMEPAGE: './index.html'
}
}
3、使用密码保护访问
(1)命令启动
- 要保护对公开文件的访问,可以设置
--basic-auth-username
和--basic-auth-password
选项。
$ pm2 serve --basic-auth-username <username> --basic-auth-password <password>
(2)配置文件
module.exports = {
script: "serve",
env: {
PM2_SERVE_PATH: '.',
PM2_SERVE_PORT: 8080,
PM2_SERVE_BASIC_AUTH: 'true',
PM2_SERVE_BASIC_AUTH_USERNAME: 'example-login',
PM2_SERVE_BASIC_AUTH_PASSWORD: 'example-password'
}
}
十、部署系统
1、部署说明
- PM2 具有简单但功能强大的部署系统,允许在生产环境中配置和更新应用程序。当您想要同时在一台或多台服务器的裸机服务器上部署应用程序时,这非常有用。
> pm2 deploy <configuration_file> <environment> <command>
Commands:
setup run remote setup commands
update update deploy to the latest release
revert [n] revert to [n]th last deployment or 1
curr[ent] output current release commit
prev[ious] output previous release commit
exec|run <cmd> execute the given <cmd>
list list previous deploy commits
[ref] deploy to [ref], the "ref" setting, or latest tag
2、部署配置
- 要配置部署系统,请向
deploy
节点添加属性 - 确保本地文件夹中的应用程序配置文件命名为
Ecosystem.config.js
或pm2.config.js
,这样您就不需要为每个命令键入配置文件名。
module.exports = {
apps : [{
script: 'api.js',
}, {
script: 'worker.js'
}],
// Deployment Configuration
deploy : {
production : {
"user" : "ubuntu",
"host" : ["192.168.0.13", "192.168.0.14", "192.168.0.15"],
"ref" : "origin/master",
"repo" : "git@github.com:Username/repository.git",
"path" : "/var/www/my-repository",
"post-deploy" : "npm install"
}
}
};
3、配置远程服务器
- 在配置远程服务器之前,请验证:
- 远程服务器安装了 PM2
- 远程服务器已授予GIT克隆目标存储库的权限
- 配置远程服务器后,您可以开始配置它们。
- 由于应用程序配置文件在本地文件夹中名为 Ecosystem.config.js 或 pm2.config.js,因此不需要每次都指定文件名
$ pm2 deploy production setup
4、部署应用
- 配置远程服务器后,您现在可以部署应用程序
- 如果 git 报告有本地更改的错误,但仍想推送远程 GIT 上的内容,则可以使用该
--force
选项强制部署。
$ pm2 deploy production
5、回滚到之前的部署
- 如果您需要回滚到以前的部署,可以使用以下
revert
选项
# Revert to -1 deployment
$ pm2 deploy production revert 1
6、在每台服务器上执行命令
- 要执行一次性运行命令,您可以使用以下
exec
选项
$ pm2 deploy production exec "pm2 reload all"
7、具体细节
(1)部署生命周期
- 进行部署时,您可以指定安装之前/之后以及更新之前/之后执行的操作
"pre-setup" : "echo 'commands or local script path to be run on the host before the setup process starts'",
"post-setup": "echo 'commands or a script path to be run on the host after cloning the repo'",
"pre-deploy" : "pm2 startOrRestart ecosystem.json --env production",
"post-deploy" : "pm2 startOrRestart ecosystem.json --env production",
"pre-deploy-local" : "echo 'This is a local executed command'"
(2)多主机部署
- 要同时部署到多个主机,您只需在属性下的数组中声明每个主机即可
host
。
"host" : ["212.83.163.1", "212.83.163.2", "212.83.163.3"],
(3)指定 SSH 密钥
- 您只需添加“key”属性以及公钥的路径,请参阅下面的示例:
"production" : {
"key" : "/path/to/some.pem", // path to the public key to authenticate
"user" : "node", // user used to authenticate
"host" : "212.83.163.1", // where to connect
"ref" : "origin/master",
"repo" : "git@github.com:repo.git",
"path" : "/var/www/production",
"post-deploy" : "pm2 startOrRestart ecosystem.json --env production"
},
8、SSH 克隆错误
pm2
在大多数情况下,这些错误是由于没有正确的密钥来克隆存储库而导致的。您需要在每一步中验证密钥是否可用。- 步骤 1 如果您确定密钥正常工作,请首先尝试
git clone your_repo.git
在目标服务器上运行。如果成功,请继续执行后续步骤。如果失败,请确保您的密钥同时存储在服务器和 git 帐户上。 - 步骤 2 默认情况下
ssh-copy-id
复制默认身份,通常命名为id_rsa
。如果这不是合适的键:
ssh-copy-id -i path/to/my/key your_username@server.com
-
这会将您的公钥添加到
~/.ssh/authorized_keys
文件中。 -
步骤 3 如果出现以下错误:
--> Deploying to production environment
--> on host mysite.com
○ hook pre-setup
○ running setup
○ cloning git@github.com:user/repo.git
Cloning into '/var/www/app/source'...
Permission denied (publickey).
fatal: Could not read from remote repository.
Please make sure you have the correct access rights and that the repository exists.
**Failed to clone**
Deploy failed
- 您可能想要创建一个 ssh 配置文件。这是确保您尝试克隆的任何给定存储库使用正确的 ssh 密钥的可靠方法。
# ~/.ssh/config
Host alias
HostName myserver.com
User username
IdentityFile ~/.ssh/mykey
# Usage: `ssh alias`
# Alternative: `ssh -i ~/.ssh/mykey username@myserver.com`
Host deployment
HostName github.com
User username
IdentityFile ~/.ssh/github_rsa
# Usage:
# git@deployment:username/anyrepo.git
# This is for cloning any repo that uses that IdentityFile. This is a good way to make sure that your remote cloning commands use the appropriate key
十一、环境变量
1、环境变量优先级
- PM2在启动新进程时将按以下顺序注入环境。
- 首先使用当前命令行环境。
- 然后使用配置文件配置的环境。
- 这里可以看到PM2会覆盖当前环境来添加
NODE_ENV=development
。
module.exports = {
apps : [
{
name: "myapp",
script: "./app.js",
watch: true,
env: {
"NODE_ENV": "development",
}
}
]
}
2、指定环境变量
- 可以在配置文件中配置不同的环境。
- 然后在执行配置文件的时候用
--env
指定具体的环境变量。 - 例如,通过
pm2 start ecosystem.config.js --env production
命令来使用env_production
,不指定即是默认环境env
。
module.exports = {
apps : [
{
name: "myapp",
script: "./app.js",
watch: true,
env: {
"PORT": 3000,
"NODE_ENV": "development"
},
env_production: {
"PORT": 80,
"NODE_ENV": "production",
}
}
]
}
3、NODE_APP_INSTANCE
-
NODE_APP_INSTANCE(PM2 2.5 最低)
环境变量用于区分进程,例如您可能只想在一个进程上运行 cronjob,您可以只检查process.env.NODE_APP_INSTANCE === '0'
。两个进程永远不会有相同的编号,在执行命令pm2 restart
或者pm2 scale
之后仍然如此。 -
如果对变量名称
NODE_APP_INSTANCE
有疑问,您可以使用instance_var
选项重命名它,变量将具有相同的行为。
module.exports = {
apps : [
{
name: "myapp",
script: "./app.js",
watch: true,
instance_var: 'INSTANCE_ID',
env: {
"PORT": 3000,
"NODE_ENV": "development"
}
}
]
}
4、increment_var
- increment_var(PM2 2.5 最小值)可以指定变化的变量。
- 如下配置,如果运行
pm2 start ecosystem.config.js
,将启动两个实例,因为PORT
的默认值是3000
,第一个实例process.env.PORT = 3000
,第二个实例process.env.PORT = 3001
- 如果运行
pm2 scale myapp 4
进行缩放,两个新实例PORT
变量为3002
和3003
。
module.exports = {
apps : [
{
name: "myapp",
script: "./app.js",
instances: 2,
exec_mode: "cluster",
watch: true,
increment_var : 'PORT',
env: {
"PORT": 3000,
"NODE_ENV": "development"
}
}
]
}