capistrano3 を利用してローカル環境で rake タスクを実行したい場合 (rake assets:precompile
や rake タスクを実行した結果を利用したい場合等)、 run_locally を使用します。
今回の環境の場合、リモートサーバー、ローカル環境ともに rbenv を利用していますが、リモートサーバーは RBENV_ROOT が/usr/local/rbenv
、rubyのバージョンは 2.1.5 を利用しているため、config/deploy.rb
には下記のような設定をしています。
set :rbenv_type, :system
set :rbenv_ruby, '2.1.5'
そして、run_locally を実行するタスクのサンプルはこちら。
namespace :sample do
desc "run_locally sample"
task "local" do
run_locally do
execute :bundle, :exec, :rake, '-T'
end
end
end
このままタスクを実行してみます。
$ bundle exec cap development sample:local
(中略)
INFO[58c12b73] Running /usr/local/rbenv/bin/rbenv exec bundle exec rake -T on localhost
DEBUG[58c12b73] Command: ( RBENV_ROOT=/usr/local/rbenv RBENV_VERSION=2.1.5 /usr/local/rbenv/bin/rbenv exec bundle exec rake -T )
cap aborted!
SSHKit::Command::Failed: bundle exit status: 32512
bundle stdout: Nothing written
bundle stderr: sh: /usr/local/rbenv/bin/rbenv: No such file or directory
(中略)
ローカル環境の RBENV_ROOT は~/.rbenv
でしたが、リモートサーバー用の環境変数が引き継がれているため、エラーが発生してしまいました。
ここでは、 run_locally でとくに rbenv の環境変数を気にせずに実行できるよう一旦下記のように修正してみます。
namespace :sample do
desc "run_locally sample"
task "local" do
run_locally do
execute "bundle exec rake -T"
end
end
end
$ bundle exec cap development sample:local
cap aborted!
SSHKit::Command::Failed: bundle exec rake -T exit status: 256
bundle exec rake -T stdout: Nothing written
bundle exec rake -T stderr: rake aborted!
LoadError: cannot load such file -- rails/all
(以下略)
こちらの記事 (http://qiita.com/paty-fakename/items/d198f441434adafaf631) を参考にさせていただいたところ、bundle exec の中で bundle exec を呼び出している状態となっているため、run_locally 内にまで環境変数を引き継いだ状態になってしまっているようです。
そこで、Bundler.with_clean_env
を利用してみます。
namespace :sample do
desc "run_locally sample"
task "local" do
run_locally do
Bundler.with_clean_env do
execute "bundle exec rake -T"
end
end
end
end
期待通りの動作になりました。
ただ、rakeタスクが別ディレクトリにある場合は、Dir.chdir('/path/to/your/.../') do
で囲ったり、:rails_env を引き継いで実行しようとするとwith rails_env: fetch(:rails_env) do
で囲ったりすることになりそうですが、なかなか深いブロックネストになりそう...うーん。