rbenvとruby-buildのインストール方法
$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
$ source ~/.bash_profile
.bash_profile
は自分の使っているシェルに応じて.zshrc
などに読み替えてください。
インストール可能なrubyバージョンの一覧表示
$ rbenv install -l
Available versions:
1.8.6-p383
1.8.6-p420
1.8.7-p249
1.8.7-p302
1.8.7-p334
(省略)
指定したバージョンのrubyをインストール
下記はバージョン2.1.2をインストールする例です。
$ rbenv install 2.1.2
使用するrubyのバージョンを指定する
rbenvでは、ディレクトリ階層ごとに使用するrubyのバージョンを指定できます。 下記はカレントディレクトリ以下で2.1.2を使用する例です。
$ rbenv local 2.1.2
rbenvによる指定が意図したように行われているかどうかは以下のように確認できます。
$ ruby --version
ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-darwin13.0]
インストール済みrubyバージョンの一覧表示
$ rbenv versions
system
2.0.0-p353
2.1.0
* 2.1.2 (set by ~/projects/xxx/.ruby-version)
systemは、/usr/bin/ruby
のようにrbenv以外の方法でシステムへインストールされたrubyです。
どのパスのコマンドが実行されるかはPATH
環境変数によって決まります。
アスタリスクの付いているバージョンが選択されたバージョンです。 カッコの内容はrbenvがそのバージョンを選択した理由です(後述)。
rbenvとは
rbenvは複数のバージョンのruby実行環境を切り替えるための仕組みです。
https://github.com/sstephenson/rbenv
rbenvには、同一の作者による ruby-build というプラグインがあります。 これは指定したrubyのソースをダウンロードして、ローカルでビルドするための仕組みです。
https://github.com/sstephenson/ruby-build
rbnevの類似のものとして rvm があります。
rbenvの仕組み
rbenvではPATH
環境変数とシンボリックリンクを用いて、
rubyやirbのようなコマンドの呼出経路に割り込むことでバージョンの切り替えを行っています。
ruby、irb、gem、およびrspecやrakeなどgemによってインストールされるコマンド群は、 以下のパスにシンボリックリンクが作られます。
~/.rbenv/shims/
これらのシンボリックリンクは、rbenv rehash
が実行されるたびに更新されます。
また、インストールの際にシェルのrcスクリプトに追加したeval "$(rbenv init -)"
というコマンドでは、下記が行われています。
PATH
環境変数の更新(export PATH="~/.rbenv/shims:${PATH}"
)- rbenv rehashの実行
これにより、ruby、irbなどのruby関連コマンドはrbenvの影響下にある~/.rbenv/shims/以下のシンボリックリンクに置き換えられています。
$ which irb
~/.rbenv/shims/irb
バージョン決定の仕組み
shims以下のコマンドでは以下のように起動するrubyインタプリタのバージョンを決定します。
RBENV_VERSION
環境変数の中身。- スクリプトの置いてあるディレクトリから上位にさかのぼって最初に見つかった
.ruby-version
ファイルの中身。 - カレントディレクトリから上位にさかのぼって最初に見つかった
.ruby-version
ファイルの中身。 このファイルはrbenv local
コマンドで作成することができます。 ~/.rbenv/version
ファイルの中身。 このファイルはrbenv global
コマンドで作成することができます。
つまり、シェルのカレントディレクトリとスクリプト自体が置いてあるディレクトリが異なり、
それぞれ.ruby-versionファイルが存在するような場合、後者が優先されます。
また、RBENV_VERSION
環境変数は常に優先されます。
例えば製品環境でgodとrbenvを使ってデーモンプロセスのrubyバージョンを指定するような場合にはこの点に注意する必要があります。
各バージョンの実体
rbenv install
でインストールしたruby実行環境は~/.rbenv/versions
ディレクトリの下に保存されます。
~/.rbenv/versions/
├── 2.0.0-p353
│ ├── bin
│ ├── include
│ ├── lib
│ └── share
├── 2.1.0
│ ├── bin
│ ├── include
│ ├── lib
│ └── share
└── 2.1.2
├── bin
├── include
├── lib
└── share
gemもこのディレクトリ以下に保存され、例えば2.1.2にインストールしたnokogiri
1.6.1の中身を見たければ以下のディレクトリにあります。
~/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/nokogiri-1.6.1/
rbenv install(ruby-build)の動作
rbenv install
は概ね以下の様な動作をします。
- CDNで配布されているrubyのソースコードをダウンロード
- ダウンロードしたソースコードを展開してビルド
このCDNは本稿執筆時点ではAmazon CloudFrontが使用されており、そのスポンサーはBasecampです。(参考)
BasecampはRailsを開発したDHHがCTOをやっている会社です。ありがとうBasecampのみなさん。
なおBasecampは去年まで37signalsという名前でした。こちらの方が馴染みが深い人が多いかもしれません。
ソースコードの配布URLはruby-build
に記述されています。
具体的には以下のパスに1ファイル1バージョンで書かれています。
$ ls -1 ~/.rbenv/plugins/ruby-build/share/ruby-build/
1.8.6-p383
1.8.6-p420
1.8.7-p249
1.8.7-p302
1.8.7-p334
1.8.7-p352
1.8.7-p357
1.8.7-p358
1.8.7-p370
1.8.7-p371
(省略)
openssl
など依存パッケージが同時に配布されている場合もあり、ビルド環境に応じてそれらもダウンロードされます。
またコードのURLにはSHA2のチェックサムが含まれており、shasum
などのツールが利用できる環境であれば自動的に改ざん検知が行われます。
$ cat ~/.rbenv/plugins/ruby-build/share/ruby-build/2.1.2
install_package "openssl-1.0.1h" "https://www.openssl.org/source/openssl-1.0.1h.tar.gz#9d1c8a9836aa63e2c6adb684186cbd4371c9e9dcc01d6e3bb447abf2d4d3d093" mac_openssl --if has_broken_mac_openssl
install_package "ruby-2.1.2" "http://cache.ruby-lang.org/pub/ruby/2.1/ruby-2.1.2.tar.gz#f22a6447811a81f3c808d1c2a5ce3b5f5f0955c68c9a749182feb425589e6635" ldflags_dirs standard verify_openssl
新しいバージョンのrubyがリリースされたら下記のように更新すれば反映されます。
$ cd ~/.rbenv/plugins/ruby-build
$ git pull
環境変数RUBY_BUILD_CACHE_PATH
でキャッシュディレクトリが指定されている場合、
rbenv install
はコードをダウンロードする代わりにそのパスに置いてあるファイルを使用します。
キャッシュディレクトリに該当するファイルがない場合にはCDNからダウンロードしたファイルをキャッシュディレクトリに保存します。
あらかじめ取得しておいたソースを使用することで、 インターネットへの接続が制限されている環境でもrbenvを使用することができます。
また、製品環境でrbenvを利用する場合にもキャッシュを用いることで外的要因に依存せずプロビジョニングを行うことができるようになります。