半年ほど前ですがアプリケーションをデプロイした先でコンソールを起動できない問題に遭遇しました。よくわからなかったのでQA@ITで質問を投げたのですが、結局解決には至らず。
AWSにデプロイしたRailsアプリケーションのコンソールを起動したいがUsageが出てしまう - QA@IT
その代わり同じような機能を実現するスクリプトを書いて回避したというところで僕としてはこの問題をスルーしていました。
デプロイ先のサーバーでrails consoleできないときの対応とCapistranoからの使い方 - ぴよログ
その原因が今更ながらわかったのでメモしておきます。
Rails4以降+binstubsで起こる問題
bundlerにbinstubsという機能があります。
$ bundle install --binstubs
とやると、実行ファイル系のgemを実行するのに便利なスクリプトを./bin
に生成してくれます。$ bundle exec cap ...
などと実行していたところを$ ./bin/cap
とタイプするだけでいける、みたいな。
ところがこの--binstubs
オプションがRails4が予め用意しているファイルを上書きしてしまいます。試しにRails4のアプリケーションを作って確認してみます。
$ rails new sample -T --skip-bundle
$ cd sample/bin
$ ls
bundle rails rake
このように3つのファイルが最初から用意されています。この状況でbundle install --binstubs
を実行するとrails
とrake
がbundlerが生成したものに上書きされてしまいrails
コマンドが正しく動かないという状況が生まれるようです。
元々あるものとbundlerが生成したものの違いはコードを読めばわかると思いますがまだ読んでません。。。
最近ではbinstubsが上書きされている場合に警告メッセージを出る機能が追加されたようです。新しいめのRails4を使用している人は気づくのかも。僕んときはベータ版だったのでそんなのなかったよ。
なぜデプロイ先のサーバーで使えなかったか
僕はローカルではbinstubsを使っていなかったので、上記の問題はアプリケーションをデプロイしたときにのみ遭遇しました。原因がなかなかわからなかったのは、デプロイをCapistranoに任せていた上、デプロイ用設定ファイルの書き方をいろいろな記事からつまみ食いしたせいで、自分でもよくわかったいなかったからです。
さっきよく見たらこんな風に書いてありました。
# config/deploy.rb for Capistrano 2.15.5
# Bundler
require 'bundler/capistrano'
set :bundle_flags, "--deployment --binstubs"
--binstubs
指定してる(´・ω・`)
特に必要なわけではないので--binstubs
を外したらうまくいきました。
binstubsを使いたいときの回避策
$ bundle install --binstubs=.bin
このように--binstubs=ディレクトリ
とすると./bin
を上書きしなくて済みます。