nvm環境でのpm2設定方法 の変更点
更新- 追加された行はこの色です。
- 削除された行はこの色です。
- ソフトウェア/nvm環境でのpm2設定方法 へ行く。
- ソフトウェア/nvm環境でのpm2設定方法 の差分を削除
#author("2026-04-02T10:33:26+00:00","default:administrator","administrator") #author("2026-04-02T11:03:48+00:00","default:administrator","administrator") [[公開メモ]] #contents * nvm 環境で pm2 を使う際の推奨設定 [#acf74c51] ** pm2 の位置づけ [#r6a26401] pm2 はプロセスマネージャーであり、''アプリケーションの外側でアプリを管理するもの''。 概念的には nginx や systemd と同じ層にいる。 ただし、ユーザーレベルの nvm と親和性があり、システムグローバル、というよりもユーザーグローバルな存在になっている。 ユーザーごとに pm2 デーモンが立ち上がり、そこで複数のプロジェクトの node サーバーを管理可能。 そのため、''pm2 は各プロジェクトの `package.json` に入れるのではなく、ユーザーグローバルにインストールする'' のがベストプラクティスとなる。 OS 起動 └── pm2(ユーザーグローバル) ├── プロジェクトA(node_modules に pm2 なし) ├── プロジェクトB(node_modules に pm2 なし) └── プロジェクトC(node_modules に pm2 なし) ** nvm 環境での推奨構成 [#uc576c85] *** pm2 を起動する Node バージョンを固定する [#m2a98485] nvm 環境ではプロジェクトごとに(実際にはフォルダー毎に)異なる node バージョンを使い分けられる しかしユーザーレベルで見ると pm2 デーモンは同時に1つだけ存在しており、それと異なる node 上の pm2 コマンドを叩くとバージョンの不一致が生じてしまう。 つまり pm2 を呼び出す際には常に''「デーモンとして常駐する pm2 と同じ Node バージョン」''を使う必要がある。 そこで、''`nvm alias default` で固定された node バージョン'' にグローバルにインストールされた pm2 をユーザーグローバルな唯一の pm2 として利用するのが良い。 LANG:console $ nvm alias default v24.14.1 $ npm install -g pm2 # あるいは pnpm global add pm2 *** pm2 自身が使う Node とアプリの Node は独立している [#s86bbf41] pm2 はアプリを子プロセスとして fork する。 起動する Node は `pm2.config.cjs` の `interpreter` で指定できる。 LANG:js // pm2.config.cjs module.exports = { apps: [{ name: 'my-app', script: './index.js', interpreter: '/home/takeuchi/.nvm/versions/node/v20.0.0/bin/node', }] } したがって pm2 デーモン自体が v24 で動いていても、アプリは v20 で動く、といった構成が可能。 `interpreter` を省略すると PATH 上の node が使われるため、''本番では明示的に指定する'' のが安全。 *** `~/bin/pm2` ラッパーで nvm を意識しない運用 [#f20a13be] プロジェクトフォルダに `.nvmrc` があって別バージョンの node が有効になっていると、そのフォルダーからユーザーグローバルの `pm2` コマンドが見えなくなる。 これを解決するために、''常に default の node 環境の pm2 を呼ぶラッパースクリプト'' を `~/bin/pm2` として用意しておく。 LANG:bash #!/bin/bash export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && source "$NVM_DIR/nvm.sh" nvm use default --silent # pm2 を呼び出すために PATH を設定 exec "$NVM_DIR/versions/node/$(nvm version default)/bin/pm2" "$@" LANG:console $ chmod +x ~/bin/pm2 このスクリプトを作ったうえで `~/bin` を PATH の先頭に置いておけば、どのプロジェクトフォルダにいても `pm2` コマンドは常に default 環境のものが呼ばれる。`$@` で全引数を透過的に渡すので、通常の pm2 コマンドがそのまま使える。 このスクリプトを作ったうえで `~/bin` を PATH に入れておけば((再起動後に)デフォルトで入る場合が多い)、どのプロジェクトフォルダにいても `pm2` コマンドは常に default 環境のものが呼ばれる(それ以外に pm2 がインストールされていない限り)。上記スクリプトは `$@` で全引数を透過的に渡しているので、通常の pm2 サブコマンドがそのまま使える。 LANG: console $ pm2 list $ pm2 restart my-app $ pm2 save pm2 自体は常に default の node で動き、''アプリが使う node は `interpreter` で個別指定'' という役割分担が明確になる。 こうすることで pm2 自体は常に default の node で動き、''アプリが使う node は `interpreter` で個別指定'' という役割分担が明確になる。 プロジェクトの `.nvmrc` は pm2 には無関係になり、nvm との関係をほぼ意識しなくてよくなる。 ** 起動時の自動起動:crontab @reboot + ラッパースクリプト [#p176f0a3] ユーザーレベルの crontab を使うことにより、 pm2 で起動したプロセスを、マシンのリブート後に自動で再起動することが可能になる。 このためにはまず、必要なプロセスをすべて立ち上げた状態で、 LANG:console $ pm2 save を行い、プロセスリストを保存しておく。 また、起動ログを取るために LANG:console $ mkdir -p ~/logs としたうえで、 $ crontab -e @reboot /home/takeuchi/bin/pm2 resurrect >> /home/takeuchi/logs/reboot-pm2.log 2>&1 のように設定すれば、pm2 save したプロセスがマシン起動時に自動実行され、 その際のログが ~/logs/reboot-pm2.log に記録される。 *** ポイント [#t1436625] - cron では .bashrc が読まれず nvm の PATH が設定されないが、~/bin/pm2 スクリプトが正しく PATH を設定したうえで pm2 を呼んでくれる - Node バージョンを変えても `nvm alias default vXX.XX.X` するだけでスクリプトは変更不要 - `pm2 resurrect` で `~/.pm2/dump.pm2` に保存済みのプロセスをすべて復元する - アプリを追加・削除したら `pm2 save` し直すだけでよい - ログに残しておくと起動失敗時の調査に役立つ *** 起動タイミングについて *** 起動タイミングについて [#g718c159] `@reboot` は OS 起動直後に実行されるため、ネットワークや DB がまだ立ち上がっていない場合がある。 ただし、アプリ側で接続リトライを実装しているか、pm2 の再起動設定を入れておけば実用上は問題になりにくい。 LANG:js // pm2.config.cjs module.exports = { apps: [{ name: 'my-app', script: './index.js', max_restarts: 10, restart_delay: 5000, // 再起動まで 5 秒待つ(ms) }] } 「DB に繋がらないから即落ちる」作りのアプリでなければ、これで吸収できるはず。 ** systemd への登録について [#e1d365ec] リブート後の pm2 再起動には、 sudo が使えるユーザー限定の代替手段として、 `pm2 startup` を使って systemd サービスファイルを生成しておく方法もある。 これはこれで `journalctl` でログを確認できる、起動順を `network.target` の後にできるといったメリットはあるのだが・・・ ''systemd に焼き込まれるのは実行時のフルパス'' なので: ExecStart=/home/takeuchi/.nvm/versions/node/v24.14.1/bin/pm2 resurrect 後から `nvm alias default` を変えても systemd は古いパスを呼び続ける。 日常の pm2 操作はログインシェルで直接行うことがほとんどなので、systemd で pm2 プロセス自体を管理できるメリットもあまり実感しにくい。 nvm を使っている環境では systemd ではなく、''crontab + ラッパースクリプトの方が追従性・シンプルさの面で素直'' と思われる。 ** まとめ [#b988b129] ユーザー takeuchi └── nvm default (v24) の node + pm2(グローバル) ├── ~/bin/pm2 ラッパー経由で常に default の pm2 を呼ぶ └── crontab @reboot + ラッパースクリプトで自動起動 └── ~/.pm2/ がそのユーザーの管理空間 └── 各アプリは interpreter で Node バージョンを個別指定 - pm2 はグローバルに1つ、プロジェクトには入れない - pm2 用 Node バージョンは `nvm alias default` で固定 - アプリが使う Node バージョンは `pm2.config.cjs` の `interpreter` で明示 - `~/bin/pm2` ラッパーにより、どのフォルダからでも nvm を意識せず pm2 を呼べる - 自動起動は crontab + ラッパースクリプトが nvm 環境では素直 - 起動タイミング問題は pm2 の `max_restarts` + `restart_delay` で吸収する * コメント・質問 [#hc3d06c7] #article_kcaptcha
Counter: 33 (from 2010/06/03),
today: 4,
yesterday: 6