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
を忘れない。