Passenger の CLI がたまにこける問題と正しい解決方法
環境
- macOS Ventura
- Apache 2.4.56
- Passenger 6.0.17
- Capistrano 3.17.2
目的
deploy ユーザーで localhost に対して Capistrano でデプロイする。
問題点
passenger-config コマンドがエラーになって Passenger を再起動できない。
エラー内容
ERROR: Phusion Passenger(R) doesn't seem to be running. If you are sure that it is running, then the causes of this problem could be:
1. You customized the instance registry directory using Apache's PassengerInstanceRegistryDir option, Nginx's passenger_instance_registry_dir option, or Phusion Passenger(R) Standalone's --instance-registry-dir command line argument. If so, please set the environment variable PASSENGER_INSTANCE_REGISTRY_DIR to that directory and run passenger-status again.
2. The instance directory has been removed by an operating system background service. Please set a different instance registry directory using Apache's PassengerInstanceRegistryDir option, Nginx's passenger_instance_registry_dir option, or Phusion Passenger(R) Standalone's --instance-registry-dir command line argument.
ChatGPT の翻訳:
エラー:Phusion Passenger(R) が実行されていないようです。実行されていることが確認できている場合、この問題の原因は以下のとおりである可能性があります:
- Apache の PassengerInstanceRegistryDir オプション、Nginx の passenger_instance_registry_dir オプション、または Phusion Passenger(R) Standalone の --instance-registry-dir コマンドライン引数を使用して、インスタンスレジストリディレクトリをカスタマイズしました。それがそうである場合、環境変数 PASSENGER_INSTANCE_REGISTRY_DIR をそのディレクトリに設定して、再度 passenger-status を実行してください。
- 操作システムのバックグラウンドサービスによってインスタンスディレクトリが削除されました。別のインスタンスレジストリディレクトリを Apache の PassengerInstanceRegistryDir オプション、Nginx の passenger_instance_registry_dir オプション、または Phusion Passenger(R) Standalone の --instance-registry-dir コマンドライン引数を使用して設定してください。
原因
Passenger の情報があるディレクトリを passenger-config が見つけられないため。
詳細
- 自分ユーザーでは passenger-status や passenger-config (以降 CLI と呼ぶ) は動く
- Passenger の情報は
${TMPDIR}passenger.*
のなかにある - deploy ユーザーに切り替えると CLI が動かなくなる
-
sudu -u 自分ユーザー passenger-status
でも動かない
対策
LoadModule passenger_module /opt/rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/passenger-6.0.17/buildout/apache2/mod_passenger.so
<IfModule mod_passenger.c>
PassengerRoot /opt/rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/passenger-6.0.17
PassengerDefaultRuby /opt/rbenv/versions/3.2.2/bin/ruby
+ PassengerInstanceRegistryDir /tmp
</IfModule>
apachectl restart
- Apache 側で
PassengerInstanceRegistryDir
を指定する - 任意のディレクトリではなく必ず
/tmp
にする- 理由は後述
-
/tmp/passenger.*
が作成されたのを確認したら次へ進む
CLI 動作確認
passenger-status
sudo -u deploy passenger-status
自分と deploy ユーザーの両方でエラーにならないのを確認する。これが通れば passenger-config restart-app /var/www/xxx-app --ignore-app-not-running
も通る。
PASSENGER_INSTANCE_REGISTRY_DIR
は定義しなくてよい
export PASSENGER_INSTANCE_REGISTRY_DIR=/tmp
や、
set :default_env, {
"PASSENGER_INSTANCE_REGISTRY_DIR" => "/tmp",
}
は必要ない。昔は必要だったのかもしれないけど今は CLI が /tmp
を探す。
CLI はどこを探しているのか?
PASSENGER_INSTANCE_REGISTRY_DIR
TMPDIR
/tmp
/var/run/passenger-instreg
/tmp/systemd-private-*-{httpd,nginx,apache2}.service-*/tmp
の順に探している。
だから任意の場所にするよりCLIが想定している場所を使った方がシンプルになる。
何もしなくても動く場合がある理由
PassengerInstanceRegistryDir
を指定しなくても動く場合がある。その理由は PassengerInstanceRegistryDir
の指定がないとき TMPDIR
の指すディレクトリが指定されているものとして Passenger が動作するから。
$ echo $TMPDIR
/var/folders/9c/_62dfc8502g_d5r05zyfwlxh0000gp/T/
であれば、
/var/folders/9c/_62dfc8502g_d5r05zyfwlxh0000gp/T/passenger.*
に書き込まれている。そして CLI も TMPDIR
を探すから動く。ただし TMPDIR
に依存する方法は脆い (続く)
deploy ユーザーに変更すると動かない理由
何もしなくても動いていたのに deploy ユーザーに変更すると動かなくなる場合がある。こうなると自分ユーザーではコマンドラインから Passenger を再起動できるのに Capistrano でデプロイすると失敗するという状況になる。
この原因は deploy ユーザーに切り替えたとき TMPDIR
が消えているから。sudo -u deploy env | grep TMPDIR
で何も出なければ消えている。つまり動いたり動かなかったりするのは deploy ユーザーというよりは TMPDIR
の有無に関係している。
この場合 visudo
で、
Defaults env_keep += "TMPDIR"
を追加する。これで deploy ユーザーに切り替えても TMPDIR
は維持されるので CLI は動く。
ただし TMPDIR
の有無が Passenger 再起動の鍵を握っているとは想像つかないし、移行アシスタントで Mac をまるごとコピーすると /etc/sudoers
は新しい Mac に転送されず、またハマることになるため、この TMPDIR
に依存して /etc/sudoers
をいじる方法は推奨しない。
/tmp
のかわりに /var/run/passenger-instreg
を使うと面倒なことになる
/var/run/passenger-instreg
を使う場合は、
sudo mkdir /var/run/passenger-instreg
として、
LoadModule passenger_module /opt/rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/passenger-6.0.17/buildout/apache2/mod_passenger.so
<IfModule mod_passenger.c>
PassengerRoot /opt/rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/passenger-6.0.17
PassengerDefaultRuby /opt/rbenv/versions/3.2.2/bin/ruby
+ PassengerInstanceRegistryDir /var/run/passenger-instreg
</IfModule>
としてから、
apachectl stop
sleep 1
apachectl start
とする。
- 設定の反映はなぜか
apachectl restart
ではダメ- stop 直後に start すると
/var/run/passenger-instreg/passenger.*
が作成されない - stop 後に1秒ぐらい待ってから start すれば作成される
- stop 直後に start すると
-
/var/run/passenger-instreg/passenger.*
があるのを確認する
core_api にアクセスできない場合
$ passenger-status
/opt/rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/passenger-6.0.17/src/ruby_supportlib/phusion_passenger/admin_tools/instance.rb:94:in `initialize': Permission denied - connect(2) for /var/run/passenger-instreg/passenger.8OqbnUO/agents.s/core_api (Errno::EACCES)
となる場合はオーナーや権限が次のようになっているか確認する。
$ ls -al /var/run/passenger-instreg
drwxr-xr-x 3 root daemon 96 4 30 12:20 .
drwxrwxr-x 38 root daemon 1.2K 4 30 12:19 ..
drwxr-xr-x 12 root wheel 384 4 30 12:20 passenger.G80V8W5
$ ls -al /var/run/passenger-instreg/passenger.G80V8W5/agents.s
total used in directory 0 available 478.2 GiB
srw-rw-rw- 1 root wheel 0 4 30 12:20 core
srw-rw-rw- 1 root wheel 0 4 30 12:20 core_api
srw-rw-rw- 1 root wheel 0 4 30 12:20 watchdog_api
その原因は?
Apache を再起動すると /var/run/passenger-instreg
の中が自分のオーナーで作成されていて、それに影響してなのか core_api も参照できない権限になっていて、これで CLI がアクセスできなくなることがあった。
その後 /var/run/passenger-instreg
を作り直したり Apache を apachectl stop
や apachectl start
しているうちに直ってしまった。
結局、何が原因でおかしくなったのかはわからない。
PCを再起動すると動かなくなる
- PCを再起動すると
/var/run/*
は消える - なので
/var/run/passenger-instreg
も消えている - Passenger は
/var/run/passenger-instreg
を自動的に作らない-
PassengerInstanceRegistryDir
で指定しているのだからそのくらいやってほしい(小声)
-
- 起動時に
/var/run/passenger-instreg
を作る方法は/Library/LaunchDaemons
以下にその処理を書いた plist を用意してsudo launchctl load なんとか.plist
すればよさそうだけど、そんな面倒なことをするぐらいなら/var/run/passenger-instreg
を使わず/tmp
にしておけばいい
この問題が顕著になった過程
- 当初はアプリ内に
tmp/restart.txt
を置くだけで再起動していた - つまり CLI と Passenger の結び付きがなくても再起動に関しては何も問題なかった
- ところが2014年ごろのバージョン 5 ぐらいから状況は一変した
-
tmp/restart.txt
を置くのではなく CLI から指示する方法が推奨となった - となると CLI と Passenger が結び付かないと再起動できなくなった
- そこで CLI と Passenger が結び付いていない場合の問題が顕著になった
まとめ
- ひとことで言えば
PassengerInstanceRegistryDir /tmp
だけを追加せよ -
/var/run/passenger-instreg
は使うな- 理由: 再起動するとディレクトリが消えるから
- デフォルトのまま使うな
- 理由: ユーザーを切り替えると
TMPDIR
がなくなるから
- 理由: ユーザーを切り替えると
-
PASSENGER_INSTANCE_REGISTRY_DIR
は定義するな- 理由: CLI が想定の場所を探し回ってくれるから
Discussion