インストールしたはずのrubyやgemが見つからなかったり古かったりした場合の確認事項

　RubyもLinuxもろくに使ったこともないのにRubyまわりの環境構築を引き継いでしまって（押し付けられて）非常に参りました。その過程で`ruby`コマンドのバージョンが古い、インストールしたはずの`gem`が見つからないなどの問題があったので、それらの状況の確認方法や解決方法、その周辺の仕組みなどを書き留めました。

# rbenvのインストール先 #

　Rubyは単品をインストールするより、`rbenv`でバージョン管理するのが一般的です。その`rbenv`ですが、[公式のインストール手順](https://www.ruby-lang.org/ja/documentation/installation/)に従うとシステム全体ではなく個別のユーザー向けにインストールさせられます。

　Apache httpdで動かしたい場合など、インストールするユーザーと実行するユーザーが異なる場合は、次の手順に従うのが良いかと思います。

[rbenvをシステムワイドにインストールする](https://office.tsukuba-bunko.org/ppoi/entry/systemwide-rbenv)

　正常な状態と比較できるように、システム全体にインストールした場合のパスを載せておきます。参考までに環境変数`$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を設定する](http://qiita.com/hitomatagi/items/a373372cb49d808c5237)

※sudoersの設定によっては普通にsudoをするだけで環境変数を引き継いでくれるそうです。

# rbenv rehash #

　`rbenv`で管理している環境の場合、`gem install`しただけではシェル上で（OSのコマンドとして）実行できません。このような`gem`は`gem install`のあと、`rbenv rehash`を実行する必要があります。

# Ansibleでのgemインストール #

　Ansibleの`gem`モジュールはデフォルトでユーザーインストールしようとするので、システム全体にインストールしたい場合は`executable`で`gem`コマンドのパスを、`user_install`に`false`を指定します。

```YAML
gem:
  name: bundler
  executable: /usr/local/rbenv/shims/gem
  user_install: false
```

[gem moduleにrbenvでインストールしたgemを使おうとしたらハマった](http://qiita.com/itiut@github/items/3e1aaa4f2b5d95efb319)

# 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 の違い](http://ka-zoo.net/2013/07/difference-of-rake-xxx-and-bundle-exec-rake-xxx/
)

`bundle exec`は省略する方法もあるそうです。

[めんどくさい bundle exec を省略する方法](http://www.techscore.com/blog/2012/10/22/%E3%82%81%E3%82%93%E3%81%A9%E3%81%8F%E3%81%95%E3%81%84-bundle-exec-%E3%82%92%E7%9C%81%E7%95%A5%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/)

　`--path`指定の有無や、指定した場合のgemインストール先は、`Gemfile`のあるディレクトリに移動して次のようにコマンドを打つと確認できます。

```
$ ls Gemfile  # Gemfileのあるディレクトリ
Gemfile
$ cat .bundle/config
---
BUNDLE_PATH: "vendor/bundle"
BUNDLE_DISABLE_SHARED_GEMS: "true"
$
```

　そもそもの`bundler`の使い方は[【Ruby】bundlerの使い方 (Gem管理)](http://www.task-notes.com/entry/20141230/1419937660)に分かりやすく書かれています。

　`--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をシステムにインストール](https://office.tsukuba-bunko.org/ppoi/entry/systemwide-rbenv)する。
* `ruby`は`rbenv`を使ってインストール。
* Ansibleで構築する場合は[zzet.rbenv](https://galaxy.ansible.com/zzet/rbenv/)を使う。
* システムにインストールする`gem`は`bundler`だけにしておく。
* そのほかの`gem`は[bundlerを使ってインストール](http://www.task-notes.com/entry/20141230/1419937660)。
* `rbenv rehash`や`bundle exec`を忘れない。