LoginSignup
9
7

More than 5 years have passed since last update.

Rubyから別のRubyのプロセスを呼ぶ

Posted at

Rubyから別のRubyプロセスをsystem関数などを使って起動する方法をまとめておく。
例えば、CRubyからJRubyなど別のバージョンのRubyを呼びたい場合に使える。

ここではrubyのバージョン管理にrbenvを使っているものとする。

まず親プロセスから呼ぶときには、シェルスクリプトを作ってその中でrubyのバージョンを切り替えるようにする。
rbenvのコマンドを使ってrubyのバージョンを切り替える。
ここではサンプルとしてCRubyからJRubyを呼ぶケースを考えよう。

sub.sh
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"
rbenv shell 'jruby-1.7.13'
ruby --version     # => jruby 1.7.13 ....

最初の2行はrbenvの初期化処理。
rbenv shell というのはそのシェルの中でのみrubyのバージョンを切り替えるコマンド。

このコマンドを呼び出すために、親プロセスの方でsystemで呼ぶ。

parent.rb
system("sub.sh")

これでうまくいくように思えるのだが、親のプロセスを bundle exec で実行している場合に問題になることがある。
bundle exec で実行すると、RUBYLIB, RUBYOPT, GEM_HOME, BUNDLE_BIN_PATH, BUNDLE_GEMFILE といった環境変数がセットされる。
環境変数は起動した子プロセスにも持ち越されるため、jrubyを起動していてもcrubyのgemのパスを検索しに行ってしまう。

これを防ぐには親プロセス側で、以下のように呼ぶ。

parent.rb
Bundle.with_clean_env do
  system("sub.sh")
end

こうすると、BundlerでセットされたBUNDLE_...環境変数がアンセットされる。
しかしRUBYLIB, GEM_HOME だけはアンセットされない。(なんで??)
ということでsystemで呼ぶ時にRUBYLIBとGEM_HOMEの環境変数をunsetする。

parent.rb
Bundle.with_clean_env do
  system({'RUBYLIB'=>nil, 'GEM_HOME'=>nil}, "sub.sh")
end

(systemの第一引数にコマンド実行時にセットしたい環境変数をHashで渡すことができます。)

9
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
7