環境
- Ruby 2.2.3
- Rails 4.2.4
- capistrano 3.4.0
- capistrano-bundler 1.1.4
- capistrano-rails 1.1.6
- capistrano-rbenv 2.0.4
- capistrano3-unicorn 0.2.1
概要
developmentサーバーから、capistranoを使用し、productionサーバーへdeploy。
productionでrails runner
コマンドをたたくと下記のエラーが出た。
ちなみに、rails c
とか、他のrailsコマンド全般でエラーが出る。
$ rails runner Tasks::TaskName.execute
/home/user/.rbenv/versions/2.2.3/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require': cannot load such file -- bundler/setup (LoadError)
from /home/user/.rbenv/versions/2.2.3/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
from /home/user/app/app_name/shared/bundle/ruby/2.2.0/gems/spring-1.6.1/lib/spring/commands.rb:33:in `<module:Spring>'
from /home/user/app/app_name/shared/bundle/ruby/2.2.0/gems/spring-1.6.1/lib/spring/commands.rb:4:in `<top (required)>'
from /home/user/.rbenv/versions/2.2.3/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
from /home/user/.rbenv/versions/2.2.3/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
from /home/user/app/app_name/shared/bundle/ruby/2.2.0/gems/spring-1.6.1/lib/spring/application.rb:77:in `preload'
from /home/user/app/app_name/shared/bundle/ruby/2.2.0/gems/spring-1.6.1/lib/spring/application.rb:143:in `serve'
from /home/user/app/app_name/shared/bundle/ruby/2.2.0/gems/spring-1.6.1/lib/spring/application.rb:131:in `block in run'
from /home/user/app/app_name/shared/bundle/ruby/2.2.0/gems/spring-1.6.1/lib/spring/application.rb:125:in `loop'
from /home/user/app/app_name/shared/bundle/ruby/2.2.0/gems/spring-1.6.1/lib/spring/application.rb:125:in `run'
from /home/user/app/app_name/shared/bundle/ruby/2.2.0/gems/spring-1.6.1/lib/spring/application/boot.rb:18:in `<top (required)>'
from /home/user/.rbenv/versions/2.2.3/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
from /home/user/.rbenv/versions/2.2.3/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
from -e:1:in `<main>'
調査
いろいろとググってみたら、
下記を実行しろやら、
$ rbenv exec bundle install
springを再起動しろやら、
$ spring stop
Spring stopped.
$ bin/spring
いろいろ情報が出てくるが、何をやっても状況変わらず。
で、springって何だろと思って、Gemfileを見てみたら、productionではインストールされないようになっている!
group :development do
# Access an IRB console on exception pages or by using <%= console %> in views
gem 'web-console', '~> 2.0'
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring'
end
productionで読み込まれないはずなのになんでspringのエラー出るの?と思っていたら下記の記事を発見。
私と同じ道をたどっている。。。
[参考] http://qiita.com/rojiuratech/items/759c2d62907a2a36e340
結局、bin/railsのファイルの中身に問題があった。
productionでは、springはインストールしてないが、bin/railsファイルで読み込もうとしている。
どうしてこんなことになるのかというと、ソースコードは、developmentでgitにpushしたものを、productionでpullしているため、本番のbin/railsのファイルの中身も、development用のままになっていた。productionでは、springをloadする必要はない。
- 変更前(development用)
#!/usr/bin/env ruby
begin
load File.expand_path('../spring', __FILE__)
rescue LoadError => e
raise unless e.message.include?('spring')
end
APP_PATH = File.expand_path('../../config/application', __FILE__)
require_relative '../config/boot'
require 'rails/commands'
- 変更後(production用)
#!/usr/bin/env ruby
APP_PATH = File.expand_path('../../config/application', __FILE__)
require_relative '../config/boot'
require 'rails/commands'
ファイルの中身を変更したら、railsコマンドが動くようになった。
しかし、capistranoを使ってdeployをしているので、毎回手動でファイルの中身を編集するわけにはいかない。
どうやら、rake rails:update:bin
というコマンドで、ファイルの書き換えができるようだ。
$ rake rails:update:bin
exist bin
identical bin/bundle
conflict bin/rails
Overwrite /home/user/app/app_name/releases/20160308034224/bin/rails? (enter "h" for help) [Ynaqdh] Y
force bin/rails
conflict bin/rake
Overwrite /home/user/app/app_name/releases/20160308034224/bin/rake? (enter "h" for help) [Ynaqdh] Y
force bin/rake
identical bin/setup
bin/rakeにもspringの記述があるのね。
とりあえず、原因は判明。
残る問題点
ただ、deploy後にrake rails:update:bin
を適用するには、
capistranoのdeploy後に、このコマンドが実行されるようにすればいいのか?
それとも、deploy.rbのlinked_dirsの設定を使って、springを読み込まない本番用のbin/rails, bin/rakeを用意して、シンボリックリンクを貼るようにすべきなのか?それとももっと良い方法があるのか、調査中です。