page_adsence

2016年3月31日木曜日

composerに関して

案件でcomposer使っていて、軽い障害になりかけた時に記憶が曖昧で自信がなかったのでメモしておく。
composer install
composer.lockファイルを元にvendor配下にソースをインストールする。
composer.lockファイルが存在していない場合は、composer.jsonを元に最新バージョンをインストールする。
composer update
composer.jsonを元に最新のソースをインストールする。
バージョンアップが発生したものに関しては、composer.lockファイルの中身が更新される。
引数でパッケージ名を指定してやると、特定のパッケージのみ更新される。

2016年2月26日金曜日

Dockerfile作成時のTIPS

基本的にはコンテナの中で一通り作業をして、それをDockerfileに記述するというスタイルで作っているのですが、
一発でDockerfileが完成することなんて無いので、なるべく効率よく作れるように下記の事を心掛けています。

1.ステップは細かく分ける。

 最終的なDockerfileはステップ数をなるべく減らす必要があるが、
 Dockerfileを作成している時にはなるべく作業単位を細かくした方が効率がいい。
 例えば、インストールに時間の掛かる処理の後ろで、処理の軽い内容をやるとする。
 長い時間掛けてインストールが終わったのに、処理の軽い方で失敗した時には、
 インストールに掛かった時間がまるごと無駄になってしまう。
 時間の掛かる処理ほど細かく分けた方が、Dockerfileを書く時には効率よく書ける。

2.キャッシュをうまく使う。

 例えばDockerfileの最初でyumなりaptなりでインストール作業を行っていたとして、
 途中別の何かをインストールする際に、追加で入れないといけないミドルウェアが出てきた場合、
 最初にインストールしているところに追記するのではなく、必要になる処理の直前で追加してやる。
 こうすることにより、途中まで作成されたキャッシュイメージを無駄にせずに済む。

2016年2月24日水曜日

Hubotをインストール

以前nodebrewを使ってnode.jsをインストールしたので、今回はhubotのインストールを行う。
$ npm install -g yo generator-hubot coffee-script
すごい色々出てくるので略
インストール出来たか確認する。
$ npm list -g generator-hubot yo coffee-script
/home/vagrant/.nodebrew/node/v5.7.0/lib
├── coffee-script@1.10.0
├── generator-hubot@0.3.1
└── yo@1.6.0
こんな感じの一覧が出てくればインストールは完了。

hubotを配置するためのディレクトリを作成。
mkdir mybot && cd mybot
自分用のhubotを作成する。
幾つか質問されるが、書いてある内容はこんな感じ。
$ yo hubot
? ==========================================================================
We're constantly looking for ways to make yo better!
May we anonymously report usage statistics to improve the tool over time?
More info: https://github.com/yeoman/insight & http://yeoman.io
========================================================================== 
→ yoの品質向上のために、使用統計や時間を匿名で報告するかもしれませんがいいですか?
Yes or No

? Owner (User )
→ 所有者は誰ですか?
自分の名前とかメールアドレスを書く

? Bot name (sanbot)
→ 作成するボットの名前
作成したディレクトリ名がデフォルトで入る様になっているので、変更する場合だけ入力する。

? Description (A simple helpful robot for your Company)
→ 概要説明
特にないので、空のままでEnter

? Bot adapter (campfire)
→ 作成したボットをどこで使うか
今回はslackを使うので、slackと入力する。
以上の項目を入力すると、ボットが作成される。
以下は出力されたログ。
$ yo hubot
? ==========================================================================
We're constantly looking for ways to make yo better!
May we anonymously report usage statistics to improve the tool over time?
More info: https://github.com/yeoman/insight & http://yeoman.io
========================================================================== Yes
                     _____________________________
                    /                             \
   //\              |      Extracting input for    |
  ////\    _____    |   self-replication process   |
 //////\  /_____\   \                             /
 ======= |[^_/\_]|   /----------------------------
  |   | _|___@@__|__
  +===+/  ///     \_\
   | |_\ /// HUBOT/\\
   |___/\//      /  \\
         \      /   +---+
          \____/    |   |
           | //|    +===+
            \//      |xx|

? Owner XXXXXXXXXXXXXX@XXXXXXXX.com
? Bot name test-bot
? Description A simple helpful robot for your Company
? Bot adapter (campfire) slackgot back false
? Bot adapter slack
   create bin/hubot
   create bin/hubot.cmd
   create Procfile
   create README.md
   create external-scripts.json
   create hubot-scripts.json
   create .gitignore
   create package.json
   create scripts/example.coffee
   create .editorconfig
                     _____________________________
 _____              /                             \
 \    \             |   Self-replication process   |
 |    |    _____    |          complete...         |
 |__\\|   /_____\   \     Good luck with that.    /
   |//+  |[^_/\_]|   /----------------------------
  |   | _|___@@__|__
  +===+/  ///     \_\
   | |_\ /// HUBOT/\\
   |___/\//      /  \\
         \      /   +---+
          \____/    |   |
           | //|    +===+
            \//      |xx|


色々出てくるので略
最後の方にツリー構造みたいなのが出てくる。
エラーが出来なければインストール完了。 botを起動してみる。
$ bin/hubot -a shell -n sanbot
   ~ 略 ~
sanbot> [Wed Feb 24 2016 07:14:55 GMT+0000 (GMT)] ERROR hubot-heroku-alive included, but missing HUBOT_HEROKU_KEEPALIVE_URL. `heroku config:set HUBOT_HEROKU_KEEPALIVE_URL=$(heroku apps:info -s  | grep web-url | cut -d= -f2)`
[Wed Feb 24 2016 07:14:55 GMT+0000 (GMT)] INFO hubot-redis-brain: Using default redis on localhost:6379
ここまで出たらEnterキーを押す。 そうすると、入力待ちの状態になるので、任意のコマンドを入力してみる。
sanbot> @sanbot ping
sanbot> PONG
ボットから返事が返って来たら完了!
終了は
sanbot> exit
で終了出来ます。

nodebrewを使ってnode.jsをインストール

最初はnvmを使っていたのですが、nodebrewの方が使いやすいらしいのでnodebrewをインストールしてみる。
CentOS7を使っている。
インストール自体はすごい簡単。
下記コマンドを実行して、パスを通すだけ。
$ curl -L git.io/nodebrew | perl - setup
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0     0    0     0    0     0      0      0 --:--:--  0:00:01 --:--:--     0
  0     0    0     0    0     0      0      0 --:--:--  0:00:03 --:--:--     0
100 23754  100 23754    0     0   6116      0  0:00:03  0:00:03 --:--:--  6116
Fetching nodebrew...
Installed nodebrew in $HOME/.nodebrew

========================================
Export a path to nodebrew:

export PATH=$HOME/.nodebrew/current/bin:$PATH
========================================
で、カレントユーザーの.bash_profileに追加
$ vi ~/.bash_profile
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi

# User specific environment and startup programs
PATH=$PATH:$HOME/.local/bin:$HOME/bin

# for nodebrew                          ← この行を追加
PATH=$PATH:$HOME/.nodebrew/current/bin ← この行を追加

export PATH
インストール可能なnode.jsのバージョンをチェック
$ nodebrew ls-remote

     ~ 略 ~

v5.0.0    v5.1.0    v5.1.1    v5.2.0    v5.3.0    v5.4.0    v5.4.1    v5.5.0
v5.6.0    v5.7.0

     ~ 略 ~
とりあえず5系の最新版をインストールする。(時間掛かる)
$ nodebrew install v5.7.0
インストール済みのnode.jsのバージョン一覧を確認する。
$ nodebrew list
v5.7.0

current: none
5.7がインストールされた事を確認出来たので、現在使用するnode.jsのバージョンを指定する。
$ nodebrew use v5.7.0
もう一回nodebrewコマンドでバージョン確認
$ nodebrew list
v5.7.0

current: v5.7.0
currentにインストールしたバージョンが出てくる様になった事を確認して、下記コマンドでnode.jsのバージョンを確認
$ node -v
v5.7.0
これでnode.jsを使える様になった。

CentOSにHeroku Toolbeltをインストールする

rubyがインストールされていないとHeroku Toolbeltは使えない。
ちなみに、CentOSの6系のリポジトリに存在しているrubyのバージョンは古く、そのrubyをインストールしてもherokuコマンドは使えない。
7系は調べてないのでわからないです・・・。
rubyのインストール方法はこちらの記事に書いたので、まだrubyがインストールされていない方は参考にして頂ければと。

Heroku Toolbeltをインストールしていく。
wget -O- https://toolbelt.heroku.com/install.sh | sh
--2015-12-29 18:33:34--  https://toolbelt.heroku.com/install.sh
toolbelt.heroku.com をDNSに問いあわせています... 54.225.72.13, 54.235.97.119, 54.235.222.159
toolbelt.heroku.com|54.225.72.13|:443 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 975 [text/plain]
`STDOUT' に保存中

 0% [                                                                                                                                           ] 0           --.-K/s              This script requires superuser access to install software.
You will be prompted for your password by sudo.
100%[==========================================================================================================================================>] 975         --.-K/s 時間 0s

2015-12-29 18:33:34 (38.1 MB/s) - stdout へ出力完了 [975/975]

Add the Heroku CLI to your PATH using:
$ echo 'PATH="/usr/local/heroku/bin:$PATH"' >> ~/.bash_profile

.bash_profileに下記の部分を追加
$ vi ~/.bash_profile
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/bin
PATH="$PATH:/usr/local/heroku/bin" ← この行を追加
export PATH

再読み込み
$ source ~/.bash_profile

パスが通っているか確認
$ which heroku
/usr/local/heroku/bin/heroku

以上でインストールは完了です。

2016年2月20日土曜日

dockerのコンテナからホストマシンへの通信

dockerコンテナ上からホストマシンにcurlとか投げれるかなと思って調べてみた。
ホストマシン上で、ifconfigコマンドを叩く。
$ ifconfig
docker0   Link encap:Ethernet  HWaddr 16:60:95:11:A4:9C
          inet addr:172.17.42.1  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::3807:43ff:fe23:6f0a/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:834595 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2501 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:26940488 (25.6 MiB)  TX bytes:647482 (632.3 KiB)
このdocker0の部分がdockerコンテナ上から見えるホストマシンのIPでした。
curlコマンドも普通に通りました。

超便利、watch iptablesコマンド

個人の開発環境の話なのですが、dockerで80番ポートを使用していたためホストマシン上で80番ポートが使えなかったので、
とりあえず8080番ポートを使おうと思ったのですが、iptalbesをオフにしたらdockerの設定が使えなくなってしまう関係でオフに出来ない状況に陥りました。
ローカルの開発環境でiptablesとかで接続出来ないと、面倒なので今までは設定オフにしちゃってたんですが、
dockerを使っている関係でそういう訳にもいかず、iptablesの設定でハマっていたのですが、同僚の人に便利なコマンドを教えてもらいました。
watch iptables -xnvL
というコマンド。
今まで使ったことないコマンドだったのですが、パケットがどの段階でどこに行っているのかが分かります。
watch iptables -xnvL
Every 2.0s: iptables -xnvL                                                                                                           Wed Feb 17 10:25:31 2016

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
     pkts        bytes          target          prot   opt in    out     source               destination
   19053  1507938   ACCEPT          all        --  *      *       0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
            0                 0   ACCEPT          icmp   --  *      *       0.0.0.0/0            0.0.0.0/0
            0                 0   ACCEPT          all        --  lo     *       0.0.0.0/0            0.0.0.0/0
          14         2264   ACCEPT          tcp      --  *      *       0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:22
          24         1408   ACCEPT          tcp      --  *      *       0.0.0.0/0            0.0.0.0/0           tcp dpt:8080
     1012       84278   IN_LOGGING  all        --  *      *       0.0.0.0/0            0.0.0.0/0
            0                 0   REJECT          all         --  *      *       0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited
見るべき点はpktsとbytes部分を特に注目してみる。
iptablesは順番が結構シビアで、間違えると思うように動いてくれないのですが、このコマンドを使うと、どこで落ちているのかよく分かる。
修正前は、
REJECT      all  --  anywhere             anywhere            reject-with icmp-host-prohibited
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:webcache
となっていたのですが、自分の認識だと上に書いた設定を下に書いた設定で上書き出来るんじゃなかったかなという朧気な記憶を元に記述したのですが、案の定間違っていました・・・。
修正前の状態を見てみると、REJECTされているパケットが・・・。
watch iptables -xnvL
Every 2.0s: iptables -xnvL                                                                                                           Wed Feb 17 10:21:20 2016

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
     pkts        bytes          target          prot   opt in    out     source               destination
   19053  1507938   ACCEPT          all        --  *      *       0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
            0                 0   ACCEPT          icmp   --  *      *       0.0.0.0/0            0.0.0.0/0
            0                 0   ACCEPT          all        --  lo     *       0.0.0.0/0            0.0.0.0/0
          14         2264   ACCEPT          tcp      --  *      *       0.0.0.0/0            0.0.0.0/0           state NEW tcp dpt:22
            0       94822   REJECT          all         --  *      *       0.0.0.0/0            0.0.0.0/0           reject-with icmp-host-prohibited
            0                0   ACCEPT          tcp      --  *      *       0.0.0.0/0            0.0.0.0/0           tcp dpt:8080
            0                0   IN_LOGGING  all        --  *      *       0.0.0.0/0            0.0.0.0/0
設定の上書きではなく、条件にマッチしなかったものが順次下に行くといった挙動でした・・・。
うろ覚えで作業するものではありませんでした・・・。

composer updateでClass not found

Laravel4.2を利用している環境で、composer updateを行うと、composer updateの後続処理として、
php artisan clear-compiled
php artisan optimize

が実行されるのですが、上記の処理を実行すると、app/config/app.phpに登録している自分で作ったServiceProviderを読み込む時にClass not foundでエラーになるという状態になっていた。
$ composer update
Loading composer repositories with package information                                                                     Updating dependencies (including require-dev)

Writing lock file
Generating autoload files
> php artisan clear-compiled
PHP Fatal error:  Class 'MyAPP\Services\App\AppServiceProvider' not found in /home/user/site/myapp/vendor/laravel/framework/src/Illuminate/Foundation/ProviderRepository.php on line 157
{"error":{"type":"Symfony\\Component\\Debug\\Exception\\FatalErrorException","message":"Class 'MyAPP\\Services\\App\\AppServiceProvider' not found","file":"\/home\/user\/site\/myapp\/vendor\/laravel\/framework\/src\/Illuminate\/Foundation\/ProviderRepository.php","line":157}}Script php artisan clear-compiled handling the post-update-cmd event returned with an error



  [RuntimeException]
  Error Output: PHP Fatal error:  Class 'MyAPP\Services\App\AppServiceProvider' not found in /home/user/site/myapp/vendor/laravel/framework/src/Illuminate
  /Foundation/ProviderRepository.php on line 157



update [--prefer-source] [--prefer-dist] [--dry-run] [--dev] [--no-dev] [--lock] [--no-plugins] [--no-custom-installers] [--no-autoloader] [--no-scripts] [--no-progress] [--with-dependencies] [-v|vv|vvv|--verbose] [-o|--optimize-autoloader] [-a|--classmap-authoritative] [--ignore-platform-reqs] [--prefer-stable] [--prefer-lowest] [--] []...
一度、自分で作ったServiceProviderをコメントアウトして、php artisan dump-autoloadし、コメントアウトを外して再度php artisan dump-autoloadすると問題なく使用出来る様になる。
使用出来る様になる理由は、vendor/composer/autoload_classmap.phpに自分で作ったServiceProviderのパスが記入されるためで、
再度composer updateするとそのファイルを含めたvendor/composer配下は再生成されるため、再びClass not foundになってしまう。

原因はcomposer.jsonに書いていたパスが間違っていたというなんとも言えないミスでした。

ディレクトリ構成は、下記の通りになっています。
/vendor/vendor_name/package_name/src/MyAPP/Service/XXXX/XXXXServiceProvider.php

誤ったcomposer.jsonの記述
"autoload": {
    "psr-4": {
        "MyAPP\\": "src/"
    }
}
正しいcomposer.jsonの記述
"autoload": {
    "psr-4": {
        "MyAPP\\": "src/MyAPP/"
    }
}
このパスが間違っているせいでautoload_psr4.phpの中の処理で引っかからずに、
autoload_classmap.phpにない場合にエラーになってしまっていました。
ちなみにcomposer内のファイル読み込み処理は、下記のファイルで行われている。
PSR-4 lookupと書かれている所の$fileに読み込むファイルのパスがセットされ、ファイルの存在確認をしている。
$ vi vendor/composer/ClassLoader.php

                            〜略〜

private function findFileWithExtension($class, $ext)
{
    // PSR-4 lookup
    $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;

    $first = $class[0];
    if (isset($this->prefixLengthsPsr4[$first])) {
        foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
            if (0 === strpos($class, $prefix)) {
                foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
                    if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
                        return $file;
                    }
                }
            }
        }
    }

    // PSR-4 fallback dirs
    foreach ($this->fallbackDirsPsr4 as $dir) {
        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
            return $file;
        }
    }

    // PSR-0 lookup
    if (false !== $pos = strrpos($class, '\\')) {
        // namespaced class name
        $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
            . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
    } else {
        // PEAR-like class name
        $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
    }

    if (isset($this->prefixesPsr0[$first])) {
        foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
            if (0 === strpos($class, $prefix)) {
                foreach ($dirs as $dir) {
                    if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
                        return $file;
                    }
                }
            }
        }
    }

    // PSR-0 fallback dirs
    foreach ($this->fallbackDirsPsr0 as $dir) {
        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
            return $file;
        }
    }

    // PSR-0 include paths.
    if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
        return $file;
    }
}
composer.jsonファイルを修正して、composer updateコマンドを打つ。 これでエラーが出なくなりました。

2016年1月29日金曜日

Laravel4.2で入力->確認->完了の画面遷移を実装してみる。(CSRF対策もおまけで)

Laravelでフォームを作るとどんな感じになるのか試してみた。
CSRF対策と2重送信の防止をするという前提で作ってみました。

app/routes.phpを編集し、入力、確認、完了画面で実行するコントローラーとアクションを定義する。
入力画面に関してはCSRF対策用のフィルタは通さずに、確認、完了画面に関してはCSRF対策用のフィルタを通す様に記述しました。
CSRF対策用のフィルタ処理はapp/filters.phpに書いてあります。(Laravelが元々用意している機能)
$ vi app/routes.php
Route::get('/input', 'HomeController@input');
Route::group(array('before' => 'csrf'), function()
{
    Route::post('/confirm',  'HomeController@confirm');
    Route::post('/complete', 'HomeController@complete');
});

続いてアクション。
下記の3つのメソッドを追加。
$ vi app/controllers/HomeController.php
public function input()
{
    return View::make('input');
}

public function confirm()
{
    return View::make('confirm');
}

public function complete()
{
    Session::regenerateToken();

    // 登録処理

    return View::make('complete');
}
完了画面で遷移してきた段階で、Laravelが作っているCSRF対策用のトークンを再生成しています。
これは、このトークンを2重送信防止用にも使用しているため、こういった形をとっています。
CSRF対策だけならこういった対応は必要ないと思います。
結局、「Session::regenerateToken()」は_tokenという名前でトークンをセッションに保存しているので、1セッションで複数フォームを開いた場合、
先に送信した方は登録されるが、後で送信された方はトークンが一致せずにエラーになる。
こういう挙動を許すかどうかは、そのシステムの要件次第なので、使用時に判断してもらえればと思います。

最後にテンプレート。
入力画面
$ vi app/views/input.blade.php
{{ Form::open(array('url' => 'confirm')) }}
<table>
<tr>
<td>タイトル</td><td>{{ Form::text('title') }}</td>
</tr>
<tr>
<td>メッセージ</td><td>{{ Form::textarea('message') }}</td>
</tr>
<tr>
<td colspan="2">{{ Form::submit('内容を確認') }}</td>
</tr>
</table>
{{ Form::close() }}

確認画面
$ vi app/views/confirm.blade.php
{{ Form::open(array('url' => 'complete')) }}
<table>
<tr>
<td>タイトル</td><td>{{ Input::get('title') }}{{ Form::hidden('title', Input::get('title')) }}</td>
</tr>
<tr>
<td>メッセージ</td><td>{{ Input::get('message') }}{{ Form::hidden('message', Input::get('message')) }}</td>
</tr>
<tr>
<td colspan="2">{{ Form::submit('内容を登録') }}</td>
</tr>
</table>
{{ Form::close() }}
完了画面
$ vi app/views/complete.blade.php
complete!

2016年1月5日火曜日

rbenvを利用してruby2系をインストール(特定のユーザーのみ)

rbenvをインストール
$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
Initialized empty Git repository in /home/vagrant/.rbenv/.git/
remote: Counting objects: 2484, done.
remote: Compressing objects: 100% (20/20), done.
remote: Total 2484 (delta 9), reused 0 (delta 0), pack-reused 2464
Receiving objects: 100% (2484/2484), 445.80 KiB | 142 KiB/s, done.
Resolving deltas: 100% (1562/1562), done.
パスを通し、ターミナル起動時に「rbenv init」する様にしておく。
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
リロード
$ source ~/.bash_profile
ruby-buildをインストール
$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
Initialized empty Git repository in /home/vagrant/.rbenv/plugins/ruby-build/.git/
remote: Counting objects: 5431, done.
remote: Total 5431 (delta 0), reused 0 (delta 0), pack-reused 5431
Receiving objects: 100% (5431/5431), 1013.75 KiB | 389 KiB/s, done.
Resolving deltas: 100% (3029/3029), done.
rbenvのバージョン確認
$ rbenv
rbenv 1.0.0-14-gc388331
Usage: rbenv  []

Some useful rbenv commands are:
   commands    List all available rbenv commands
   local       Set or show the local application-specific Ruby version
   global      Set or show the global Ruby version
   shell       Set or show the shell-specific Ruby version
   rehash      Rehash rbenv shims (run this after installing executables)
   version     Show the current Ruby version and its origin
   versions    List all Ruby versions available to rbenv
   which       Display the full path to an executable
   whence      List all Ruby versions that contain the given executable

See `rbenv help ' for information on a specific command.
For full documentation, see: https://github.com/rbenv/rbenv#readme
rubyをインストールする際に必要になるパッケージをインストール
$ sudo yum install gcc make openssl-devel readline-devel
インストール可能なrubyのバージョンの一覧を確認する
$ rbenv install -l
Available versions:
  :
  略
  :
  2.2.0
  2.2.1
  2.2.2
  2.2.3
  2.2.4
  2.3.0-dev
  2.3.0-preview1
  2.3.0-preview2
  2.3.0
  2.4.0-dev
  :
  略
  :
今回はとりあえず2.2.4をインストールしてみる。
$ rbenv install 2.2.4
Downloading ruby-2.2.4.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.2/ruby-2.2.4.tar.bz2
error: failed to download ruby-2.2.4.tar.bz2

BUILD FAILED (CentOS release 6.7 (Final) using ruby-build 20151230)
ダウンロードに失敗したのでログを確認。 ググると、時間が一致していない事が問題らしいので、サーバ側の時間を現時刻に合わせた。(ntp入れた)
tail /tmp/ruby-build.YYYYMMDDHHIISS.XXXX.log
curl: (60) Peer certificate cannot be authenticated with known CA certificates
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.
現時刻があったことを確認して、下記コマンドを再度実行。
$ rbenv install 2.2.4
Downloading ruby-2.2.4.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.2/ruby-2.2.4.tar.bz2
Installing ruby-2.2.4...
Installed ruby-2.2.4 to /home/vagrant/.rbenv/versions/2.2.4
デフォルトで使用するrubyのバージョンを下記の通りにする。
$ rbenv global 2.2.4
バージョンを確認(rubyコマンドが見つからない場合は、$ source ~/.bash_profileする)
$ ruby -v
ruby 2.2.4p230 (2015-12-16 revision 53155) [x86_64-linux]
以上でインストールは完了。