Passenger 3 で RVM の Ruby を使う
このページでは、Phusion Passenger 3 で RVM を使用するための手順を説明します。Phusion Passenger 4 以降にアップグレードすることを強く推奨します。なぜなら、そちらの方が RVM のサポートがより優れているからです。Phusion Passenger 4 の手順についてはこちらのページをご覧ください。
Passenger 3
Passenger は基本的に Nginx と Apache の両方に対する「mod_ruby」です。Passenger 3 アプリケーションをすべて実行するために、*正確に1つ*の Ruby を選択できます。複数の Ruby インタプリタを実行する必要がある場合は、最も一般的なものを選択する必要があります。その後、異なる Ruby で異なるアプリケーションを実行するために、Passenger Standalone、Unicorn、Thin、Mongrel、Mongrel2 などの外部アプリケーションサーバーへのプロキシパスを使用します。これについての完全な説明(美しい画像付き!)については、Phusionのブログの投稿を参照してください。
Passenger を使用した Nginx/Apache のインストール
まず、passenger-install-apache2-module と passenger-install-nginx-module があります。インストール終了時に、Webサーバーの PassengerRuby 設定スニペットが出力されます。その値は、インストーラーを実行するために使用されたRVM RubyおよびRVM gemsetに対応するRVM Rubyラッパースクリプトに設定されています。これがPassenger 3の設定に必要なすべてであるはずです!
.rvmrc ファイルを作成する代わりに、.ruby-version または .versions.conf のような新しい形式を使用してください。
echo 1.9.3@my-app-name > .ruby-version
次に、Railsプロジェクトに新しいファイル config/setup_load_paths.rb を追加し、RVM 1.12.0(またはhead)以降、RVMはデフォルトgemsetにgemとしてインストールされるため、$LOAD_PATHをunshiftする必要はありませんが、GEM_PATHを設定する必要があります。config/setup_load_paths.rb
if ENV['MY_RUBY_HOME'] && ENV['MY_RUBY_HOME'].include?('rvm') begin gems_path = ENV['MY_RUBY_HOME'].split(/@/)[0].sub(/rubies/,'gems') ENV['GEM_PATH'] = "#{gems_path}:#{gems_path}@global" require 'rvm' RVM.use_from_path! File.dirname(File.dirname(__FILE__)) rescue LoadError raise "RVM gem is currently unavailable." end end # If you're not using Bundler at all, remove lines bellow ENV['BUNDLE_GEMFILE'] = File.expand_path('../Gemfile', File.dirname(__FILE__)) require 'bundler/setup'
Passenger 3では、passenger_rubyラッパーを使用する必要はなく、rubyラッパースクリプトを直接使用するようになったことに注意してください。
Passenger Standalone の起動
次に、Passenger Standalone、つまり「passenger start」があります。Passenger Standaloneは内部的にNginxを使用しており、Nginx設定ファイルにpassenger_rubyディレクティブを書き込みます。このディレクティブは、「passenger start」コマンドを実行するために使用されたRVM RubyおよびRVM gemsetに対応するRVM Rubyラッパースクリプトを指します。
Bundler の落とし穴
プロジェクトでBundlerを使用すると、Passengerは賢く動作し、Gemfileにリストされているgemのみを$LOAD_PATHに追加しようとします。これにより、リストされていないgemで「unable to load」エラーが発生する可能性があります(これは開発中にのみ発生するはずです)。実行時のロードパスを確認するには、次を追加します。
f = File.open('/tmp/load_path', 'w') f.write($:) f.close
アプリのメインファイルに(「require」呼び出しの前)。そのロードパスにないgemはロードできません。
トラブルシューティング
- 最も一般的な問題は、適切なラッパースクリプトを取得するためにパスの /bin/ 部分を忘れることです。
- 次に多いのは、passenger_ruby/PassengerRuby の場所に関する passenger インストールスクリプトの出力に従うことです。上記のように指定されたラッパースクリプトの場所を使用してください。より明確にするために、以下のnginxの例を参照してください。
passenger_ruby /home/wayne/.rvm/bin/passenger_ruby; * NOTICE THE '.rvm/bin' DIR ^ ^ ^ * do NOT use the actual ruby binary in .rvm/rubies/{passenger_ruby}/bin/ruby * do not listen to passenger's output for passenger_ruby as passenger is not aware of rvm.
システム全体(root)インストールの場合、binディレクトリは /usr/local/rvm/bin になります。passenger_ruby /usr/local/rvm/bin/passenger_ruby;
FAQ
-
Q: Passengerで複数のプロジェクトを、各プロジェクトを異なるrubyバージョンで実行できますか?
A: Passenger 3は*1つ*のRubyでの実行のみをサポートしていますが、プロキシパスを使用することでサイト/プロジェクトごとの動作を実現できます。
-
Q: Passengerでカスタムgemsetを使用するにはどうすればよいですか?
A: Bundlerを使用しない場合は、config.ruで次のように環境変数を自分で設定できます。
ENV["GEM_HOME"]=%x{"source ~/.bash_profile ; rvm ree@pancake ; rvm gemdir"}.strip
A: Bundlerを使用する場合:任意のgemset外にbundlerをインストールし、使用したいgemsetに切り替えて実行します。bundle installそして、アプリケーションを再起動します(tmp/restart.txtに触れることで)。これは、bundlerが絶対パスを内部に保存するためです。.bundle/environment.rbこれはbundlerによって直接ロードされます。これが期待どおりに機能しない場合は、次のようにbundle installを実行してみてください。
bundle install $BUNDLE_PATH
ユーザーインストールと組み合わせてpassenger-statusのようなコマンドを使用できますが、それらをrootとして実行するにはどうすればよいですか? 主に、これの鍵となるのは、次の例に示すようにsudoersファイルでワイルドカードを使用することです。
/usr/bin/env GEM_PATH=* GEM_HOME=* PATH=* passenger-status
これはRVM 1.12.0より前のバージョン用のconfig/setup_load_paths.rbです。
if ENV['MY_RUBY_HOME'] && ENV['MY_RUBY_HOME'].include?('rvm') begin rvm_path = File.dirname(File.dirname(ENV['MY_RUBY_HOME'])) rvm_lib_path = File.join(rvm_path, 'lib') # $LOAD_PATH.unshift rvm_lib_path require 'rvm' RVM.use_from_path! File.dirname(File.dirname(__FILE__)) rescue LoadError # RVM is unavailable at this point. raise "RVM ruby lib is currently unavailable." end end # Pick the lines for your version of Bundler # If you're not using Bundler at all, remove all of them # Require Bundler 1.0 ENV['BUNDLE_GEMFILE'] = File.expand_path('../Gemfile', File.dirname(__FILE__)) require 'bundler/setup' # Require Bundler 0/9 # if File.exist?(".bundle/environment.rb") # require '.bundle/environment' # else # require 'rubygems' # require 'bundler' # Bundler.setup # end