RubyもLinuxもろくに使ったこともないのにRubyまわりの環境構築を引き継いでしまって(押し付けられて)非常に参りました。その過程でrubyコマンドのバージョンが古い、インストールしたはずのgemが見つからないなどの問題があったので、それらの状況の確認方法や解決方法、その周辺の仕組みなどを書き留めました。
rbenvのインストール先
Rubyは単品をインストールするより、rbenvでバージョン管理するのが一般的です。そのrbenvですが、公式のインストール手順に従うとシステム全体ではなく個別のユーザー向けにインストールさせられます。
Apache httpdで動かしたい場合など、インストールするユーザーと実行するユーザーが異なる場合は、次の手順に従うのが良いかと思います。
正常な状態と比較できるように、システム全体にインストールした場合のパスを載せておきます。参考までに環境変数$RBENV_ROOTも載せておきます。もし$RBENV_ROOTが設定されていなかったら前述のサイトのeval "$(rbenv init -)"が実行されていなので実行してください。
$ which rbenv
/usr/local/rbenv/bin/rbenv
$
$ which ruby
/usr/local/rbenv/shims/ruby
$
$ which bundle
/usr/local/rbenv/shims/bundle
$
$ echo $RBENV_ROOT
/usr/local/rbenv
$
Ansibleを使えるのであれば、Ansible galaxyで公開されているroleを拝借するのが手っ取り早くて良いかと思います。
zzet.rbenv
https://galaxy.ansible.com/zzet/rbenv/
https://github.com/zzet/ansible-rbenv-role
ansibleの設定が置いてあるディレクトリ(/etc/ansibleなど)で次のコマンドを実行するとrolesの直下にインストールできます。
$ sudo ansible-galaxy install zzet.rbenv
$
$ ls roles/ | grep rbenv
zzet.rbenv
$
インストールしたrubyのバージョン
バージョン確認するのは単純にruby -vですが、新しいrubyをインストールしたはずなのにバージョンが古いまま変わっていない場合があります。下記のようにrbenv installしただけではバージョンは変わらないのでrbenv globalまたはrbenv localでバージョンを選択します。rbenv localのインストールを行った場合は特定のディレクトリ配下だけバージョンが変わるので、バージョン確認は、rubyを実行したい場所でruby -vを行ってください。
# # rbenv installしただけではバージョンは変わらない
#
# rbenv install 2.4.0
# ruby -v
ruby 2.3.3p222 (2016-11-21 revision 56859) [x86_64-linux]
#
# # バージョン変更
#
# rbenv global 2.4.0
# ruby -v
ruby 2.4.0p0 (2016-12-24 revision 57164) [x86_64-linux]
#
# # ruby2.3ディレクトリでは ver 2.3.3にする。
#
# cd ruby2.3/
# rbenv local 2.3.3
# ruby -v
ruby 2.3.3p222 (2016-11-21 revision 56859) [x86_64-linux]
#
# # ruby2.3ディレクトリの外では ver 2.4.0
#
# cd ..
# ruby -v
ruby 2.4.0p0 (2016-12-24 revision 57164) [x86_64-linux]
#
rbenv localを実行した場所では.ruby-versionというファイルが作成されていて、その中身はrbenv localで指定したバージョンになっています。
$ cd ruby2.3/
$
$ cat .ruby-version
2.3.3
$
sudoで実行する場合
rbenvを使用している環境でrubyコマンドやgemをインストールする際、あるいは状況を確認する際にsudoを使うこともありますが、sudoの場合は(必要なオプションを指定しないと)コマンドが見つかりません。
$ rbenv -v
rbenv 1.0.0
$ sudo rbenv -v
sudo: rbenv: command not found
#
sudoでは、次のように環境変数PATHが引き継がれないためです。
$
$ sudo env | grep PATH
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
$
$ env | grep PATH
PATH=/usr/local/rbenv/shims:/usr/local/rbenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$
sudo -iならば実行できます。
$ sudo -i rbenv -v
rbenv 1.0.0
$
もしくは、絶対パスを指定します。
$ /usr/local/rbenv/bin/rbenv -v
rbenv 1.0.0
$
Ansibleの場合で、環境変数を渡す方法を試した方もいるようです。
Ansibleのenvironmentを利用して「sudo su -」相当のPATHを設定する
※sudoersの設定によっては普通にsudoをするだけで環境変数を引き継いでくれるそうです。
rbenv rehash
rbenvで管理している環境の場合、gem installしただけではシェル上で(OSのコマンドとして)実行できません。このようなgemはgem installのあと、rbenv rehashを実行する必要があります。
Ansibleでのgemインストール
Ansibleのgemモジュールはデフォルトでユーザーインストールしようとするので、システム全体にインストールしたい場合はexecutableでgemコマンドのパスを、user_installにfalseを指定します。
gem:
name: bundler
executable: /usr/local/rbenv/shims/gem
user_install: false
gem moduleにrbenvでインストールしたgemを使おうとしたらハマった
bundle exec
bundlerを使っている場合、bundle install実行時に必要に応じてgemがインストールされますが、このときにgemのインストール先を指定できます。たとえば
bundle install --path vendor/bundle
のように実行します。
上記のように、--pathを指定してbundle installした場合、環境変数PATHが通っていない場所にgemがインストールされるので、そのままではインストールしたgemコマンドを実行できません。bundle exec rakeのように先頭にbundle execをつけると、bundle install時に--pathの指定があろうとなかろうと指定したgemを実行できます。
rake xxx と bundle exec rake xxx の違い
bundle execは省略する方法もあるそうです。
--path指定の有無や、指定した場合のgemインストール先は、Gemfileのあるディレクトリに移動して次のようにコマンドを打つと確認できます。
$ ls Gemfile # Gemfileのあるディレクトリ
Gemfile
$ cat .bundle/config
---
BUNDLE_PATH: "vendor/bundle"
BUNDLE_DISABLE_SHARED_GEMS: "true"
$
そもそものbundlerの使い方は【Ruby】bundlerの使い方 (Gem管理)に分かりやすく書かれています。
--pathをした場合でirbを使いたいとき、普通にirbを実行するとgemが見つかりません。その代わりに、bundle consoleを実行して、irb起動中にBundler.requireを実行します。
$ # Gemfileで 'rest-client'というGemを管理
$
$ grep rest-client Gemfile
gem 'rest-client'
$
$ bundle console
> RestClient
=> RestClient
>
まとめ
やり方がいろいろありそうですが、とりあえず無難そうなものはこうかなと思います。
- rbenvをシステムにインストールする。
-
rubyはrbenvを使ってインストール。 - Ansibleで構築する場合はzzet.rbenvを使う。
- システムにインストールする
gemはbundlerだけにしておく。 - そのほかの
gemはbundlerを使ってインストール。 -
rbenv rehashやbundle execを忘れない。