pm2でNode.js実行環境を整備する

過去に、とりあえず、pm2でNode.jsの実行環境を作ったのですが、Node.jsにも慣れてきたので、pm2の設定を見直すとともに、備忘録として残しておこうと思います。
また、Webで実行状態を把握できるpm2-guiもインストールします。

pm2は、node.jsアプリの実行状態の永続化やプロセスの状態、ログの管理など、Node.jsアプリの実行管理に有用なアプリです。

# pm2インストール

NPMを使ってインストールします。

> npm install pm2 -g

[参考情報]
https://pm2.io/doc/en/runtime/overview/

rootアカウントで起動する場合は、rootアカウントでログインした状態で上記を実行します。

実行するNode.jsアプリは、JSON形式の設定ファイルに指定します。
たとえば、以下に置きます。

/etc/pm2/pm2.config.js

[参考情報]
https://pm2.io/doc/en/runtime/reference/ecosystem-file/

```pm2.config.js
module.exports = {
  apps : [
  {
    name: "Application Name(4001)",
    script: "./app.js",
    cwd : '/home/XXXX/YYYY/',
    env: {
      PORT: 4001,
      NODE_ENV: "development",
    },
    env_production: {
      PORT: 4001,
      NODE_ENV: "production",
    }
  }
  ]
}
```

nameには、区別がつきやすいように、適当な名前を付けておきます。( )でポート番号を明記しておくと、(後々説明しますが)わかりやすいです。
scriptには、実行コマンドを指定するのですが、jsファイルを指定した場合、自動的にnode.jsと判断して、nodeで実行してくれます。
cwdは、実行時のカレントディレクトリを指定します。scriptで指定するNode.jsファイルの位置に合わせます。
envは、各種環境変数を指定します。production時、それ以外の時のように、分けて指定できます。

とりあえず、上記の設定で、pm2でNode.jsアプリを起動してみます。

> pm2 start [設定ファイル名]

例) pm2 start /etc/pm2/pm2.config.js

よく使うコマンドを示しておきます。

* pm2 start [設定ファイル名]
 * pm2を起動し、設定ファイル名に従ってNode.jsアプリを起動します。
* pm2 status
 * 現在のpm2によるNode.jsアプリの起動状態を表示します。また、各Node.jsアプリのidも表示します。
* pm2 show [id]
 * 指定したidのNode.jsアプリの状態を表示します。
* pm2 restart [id]
 * 指定したidのNode.jsアプリを再起動します。
* pm2 stop [id]
 * 指定したidのNode.jsアプリを停止します。一時的に一部のNode.jsアプリだけ停止したい時に使います。
* pm2 start [id]
 * 指定したidのNode.jsアプリを起動します。一時的に停止したNode.jsアプリを起動します。
* pm2 kill
 * pm2を終了します。

ログファイルは、特に指定がない場合、実行ユーザの以下のフォルダに格納されます。

~/.pm2/logs/

各Node.jsアプリごとに生成され、ログファイル名は、pm2 show [id] で確認できます。


# pm2の自動実行設定

OS起動時に、pm2が自動起動するようにします。
今回は、対象としてRaspberry Piとして、systemdとして設定します。

先に言っておくと、以下の方法で、systemdの設定ファイルを作成できるのですが、それをベースとして改造します。


> pm2 dump
pm2 startup
cd /etc/systemd/system
cp pm2-root.service pm2.service
chmod 664 pm2.service
pm2 unstartup


改造内容は、設定ファイルを指定するようにすることです。
最終的に以下のようになります。

```pm2.service
[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=/root/.nvm/versions/node/v8.11.3/bin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
Environment=PM2_HOME=/root/.pm2
PIDFile=/root/.pm2/pm2.pid

#ExecStart=/root/.nvm/versions/node/v8.11.3/bin/pm2 resurrect
ExecStart=/root/.nvm/versions/node/v8.11.3/bin/pm2 start /etc/pm2/pm2.config.js
#ExecReload=/root/.nvm/versions/node/v8.11.3/bin/pm2 reload all
ExecReload=/root/.nvm/versions/node/v8.11.3/bin/pm2 reload /etc/pm2/pm2.config.js
ExecStop=/root/.nvm/versions/node/v8.11.3/bin/pm2 kill

[Install]
WantedBy=multi-user.target
```

このファイルを以下に配置します。

> /etc/systemd/system/pm2.service

早速、systemdとして実行してみます。

> systemctl start pm2

実行状態は、以下で確認できます。

> systemctl status pm2

うまくいかなければ、~/.pm2/logs/にあるログファイルを確認してください。
特に問題がなければ、Raspberry Pi起動時に自動実行するように設定します。

> systemctl enable pm2

これで、自動実行されるようになりました。


# pm2-guiインストール

pm2から起動したNode.jsファイルの実行状態をブラウザから確認できるようにするために、pm2-guiをインストールします。

pm2-guiを使うと、Webブラウザから以下のことができるようになります。

* マシン全体のメモリ使用量・CPU負荷を確認できる。
* pm2で管理しているアプリの一覧を確認したり、削除したりできる。
* 各アプリを一時的に停止したり、再起動したりできる。
* 各アプリのメモリ使用量・再起動回数を確認できる。
* 各アプリの起動時パラメータを確認できる。

以下の通りにインストールします。

> npm install pm2-gui -g

[参考情報]
https://github.com/Tjatse/pm2-gui

設定ファイルを作成します。
例えば、以下に配置します。

/etc/pm2/pm2-gui.ini

何もしないと、誰でもページを見れてしまうので、パスワードで保護します。
そのために、 authorization=XXXXXXXXX を加えています。XXXXXXXXX はパスワードになりますので、秘匿の任意の値にして下さい。
portは、待ち受けるWebページのポート番号です。
内容は以下の通りです。

```ini:pm2-gui.ini
;
; Home directory of pm2.
;
pm2 = ~/.pm2
;
; The interval between communications of Monitor.
;
refresh = 5000
;
; Port of Web server and socket agent.
;
port = 8088
;
; A value indicates whether or not run the pm2-gui damonized.
;
daemonize = true
;
; A value indicates whether or not the action buttons (i.e. `restart`, `stop all`...) should be displayed on web page.
;
readonly = false

[log]
;
; Log directory.
;
dir = ./logs
;
; A value indicates whether or not display the [INFO], [ERROR].. prefixes before log message.
;
prefix = true
;
; A value indicates whether or not display the local date string before log message.
;
date = false
;
; Log level, one of debug, log, info, warn, error.
;
level = warn
;
; Socket.io origins check, e.g.:
;   origins = 'example.com:* http://example.com:* http://www.example.com:8088'
; By default:
;   origins = *:*

[agent]
;
; This authorization will be used to authorize socket / web connections if it's set.
;
authorization = XXXXXXXXXXXX
;
; A value indicates whether agent offline or not.
;
; offline = true
[remotes]
;
; the dashboard and web server will use this section to connect remoting socket server
;   server_name = [authorization@]host:port
;
; pm2@171 = AuTh@https://192.168.1.171:9002/sockserv
; pm2@172 = 192.168.1.172:9001
; pm2@173 = 192.168.1.173:9000
;
```

パスワードを記入したので、一般ユーザは参照できないようにします。

> chmod og-rwx /etc/pm2/pm2-gui.ini

では、実行します。

先に、PM2を起動しておきます。

> systemctl start pm2

pm2-guiを起動します。

> pm2-gui start /etc/pm2/pm2-gui.ini

※起動時に何かエラーがでますが、起動はできているようです。

ブラウザから以下を表示してみます。

http://localhost:8088

パスワードの入力を促されます。pm2-gui.iniに指定したパスワードを入力します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/261826/22ef78ab-0199-90d3-1762-562b11ae6b57.png)
 

成功すると、以下のように表示されます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/261826/8355398e-baad-0087-5dba-25d309bb721c.png)

Processesのページでは、Node.jsアプリの名前(name)の一覧が表示されます。
pm2.config.jsにおいて、nameに( )でポート番号を記載しておくと、ここで各Node.jsアプリが待ち受けているポート番号がわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/3dbaeeef-bc23-ca89-fc14-3153a3cf1d54.png)

# pm2-guiの自動実行設定

pm2-guiの起動に成功したので、pm2-guiも自動起動するようにします。
一旦、pm2-guiは終了しておきます。

> pm2-gui stop

それでは、pm2-gui用のsystemdファイルを作成します。

/etc/systemd/system/pm2-gui.service

```pm2-gui.service
[Unit]
Description=pm2-gui process manager
After=network.target pm2.service

[Service]
Type=forking
User=root
Environment=PATH=/root/.nvm/versions/node/v8.11.3/bin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin

ExecStart=/root/.nvm/versions/node/v8.11.3/bin/pm2-gui start /etc/pm2/pm2-gui.ini
ExecReload=/root/.nvm/versions/node/v8.11.3/bin/pm2-gui restart
ExecStop=/root/.nvm/versions/node/v8.11.3/bin/pm2-gui stop

[Install]
WantedBy=multi-user.target
```

ポイントは、After=のところに、pm2.serviceを指定しているところです。pm2が起動した後にpm2-guiを起動する順番にしたいためです。

> chmod 664 pm2-gui.service
> systemctl daemon-reload
> systemctl start pm2-gui

もう一度、以下のURLをブラウザから参照して成功すればOKです。

http://localhost:8088

自動起動設定します。

> systemctl enable pm2-gui

最後に、Raspberry Piをリブートして、pm2とpm2-guiが自動起動されていることを確認しましょう。

# 補足

以下もぜひご参考に。

[PM2をもっともっと快適に！](https://qiita.com/poruruba/items/90c0fa66d0e94a8fc07f)
[PM2をブラウザから管理する](https://qiita.com/poruruba/items/55d3a08550e03f0b549c)

以上です。