PM2检查进程状态并重启

Node.js项目常用PM2部署,遇到了一个问题。

首先介绍一下PM2启动script的方法。

常规的NPM启动脚本方式是 npm run <script-name>,例如 npm run start或者npm run dev

使用PM2调用NPM执行脚本的方法如下,其中<name>为指定PM2中进程的名称( 执行pm2 list 显示在name一列)。

1
pm2 start npm --name <name> -- run <script-name>

问题

系统重启后,PM2的进程列表是空的。第一次要启动一个项目时,需要执行完整的start命令,指定要执行的script或者js文件,PM2会创建一个进程,并生成名称(或者使用参数指定的名称)。如果名称重复了,会自动加后缀序号生成新的名称。

进程创建完成后,就会一直保留在PM2的进程列表中,而之后无论是启动、停止还是重启,都应该使用进程的name。

1
2
3
pm2 start <name>
pm2 stop <name>
pm2 restart <name>

如果进程停止后,重新启动时使用的不是pm2 start <name>,而是重新执行完整的start命令,PM2会生成一个新的进程,并在名称末尾加序号。这样之后再要停止、重启这个进程,就需要用新的name。

PM2的这种设计,导致在不同的情况下(进程还没创建和已经创建),启动一个app要用的命令不一样,需要人工判断并执行相应的命令。因此希望能有一个脚本,自动判断PM2中的进程状态,自动启动或者重启项目。

需求

  • 检查PM2中指定名称的进程是否创建
  • 如果没创建,则执行完整的pm2 start命令,启动进程并指定名称
  • 如果已经创建了,则直接重启该进程

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
function restartPm2Script() {
NAME=$1;
SCRIPT=${2:-start}
pm2 describe $NAME > /dev/null
RUNNING=$?
if [ "${RUNNING}" -ne 0 ]; then
echo "start app '$NAME'..."
pm2 start npm --name $NAME -- run $SCRIPT
else
echo "restart app '$NAME'..."
pm2 restart $NAME
fi;
}

用法如下,其中my-app为app的名字,start为执行的npm脚本,即package.jsonscripts字段定义的脚本。

1
2
3
restartPm2Script my-app start
# 不指定第二个参数则默认为start
restartPm2Script my-app

参考:

https://github.com/Unitech/pm2/issues/325