QA@IT

Capistrano3で、rvmのPATHが通らない。

4120 PV

現在、Capistrano3とRails4.0を使って、RVMでRubyがインストールされたサーバ上に、Railsのデプロイを行いたいと考えています。
しかしながら、Rails等のPATHがうまく通らず、command not foundになってしまいます。

具体的な状況を説明させていただきます。
CapsistranoでPATHが取っている事を確認したいため、以下のようなdeploy.rbを書きました。

namespace :deploy do
  desc 'Restart application'
  task :restart do
    on roles(:app), in: :sequence, wait: 5 do
        info capture "printenv PATH"
    end
  end
end

実行結果は以下の様になっています。

DEBUG [ffeafec3] Command: printenv PATH
DEBUG [ffeafec3]    /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

この通り、PATHにrvmが通っていません。

次に、私がこのPATHのバグを修正するために、やったことを書かせていただきます。

  • capistrano-rvmを使う

GemFileに以下の様に書きます。

group :development do
  gem 'capistrano', '~> 3.0'
  gem 'capistrano-bundler'
  gem 'capistrano-rails'
  gem 'capistrano-rvm'
end

そして、Capfileに

require 'capistrano/rvm'

と書きました。
しかしながら、printenv PATHの内容は変わりませんでした。

  • default_environmentにPATHを書く。

ネット上で下記の様に書くと、PATHを変更できると書いていたので、deploy.rbに書いてみました。

set :default_environment, {
    'PATH' => "/home/username/.rvm/gems/ruby-1.9.3-p194/bin:$PATH:
}

しかしこれも変わりませんでした。

  • bash.rcとbash_loginに書いてある内容を実行する

Capistranoの問題はおそらくこの当たりのシェルを叩いてないため、PATHが通っていないと考えました。
そのため、Cpaistranoに叩かせました。

execute '[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm"'
execute "PATH=$PATH:$HOME/.rvm/bin"

しかしこれも変わりませんでした。

execute '[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" && printenv PATH'

とするとPATHが通っていたようなので、どうもCapistranoは一回一回のコマンド毎にPATHが初期化されているようです。

どうすれば、Capistaranoにrvmのパスを通す事が出来るでしょうか?
ご回答いただけると幸いです。

回答

返事遅れてすいません。長くなる+ソースがあるので回答で返事をさせていただきます。

結果からいうと、ご回答いただいた、

within(current_path){ bundle "exec", "unicorn_rails", ... }

でうまくいけました。

ただいくつかこのGemを使う上ではまったので、書かせていただきます。

set :rvm_ruby_version, "ruby-1.9.3-p194"

execute :bundle

こうやって実行すると。

/bin/rvm ruby-1.9.3-p194 do bundle

が実行され、

bash: /bin/rvm: No such file or directory

になりました。

そこでgemにpryを引っ掛けてみると、[:rvm_path]/bin/rvmの様に書かれていて、fetch(:rvm_path)が空なことが原因の様でした。

そこでrvm_pathを指定して、

set :rvm_ruby_version, "ruby-1.9.3-p194"
set :rvm_path,"~/.rvm"

namespace :deploy do
  desc 'Restart application'

  task :restart do
    on roles(:app), in: :sequence, wait: 5 do
      within("railsproject_path") do
        execute :bundle,"exec unicorn_rails"
      end
    end
  end
end

の様に実行するとうまくいきました。ありがとうございました。

編集 履歴 (0)

未検証なので間違いがあるかもしれません。

capistrano-rvm については、READMEソースをみる限り、PATH を追加しているのではなく、gem、rake、ruby、bundle メソッドで /path/to/rvm Rubyのバージョン do コマンド が実行されるよう設定しているようです。

これを使って、たとえば rake タスクを実行する場合は、execute "rake taskname" ではなく、rake "taskname" あるいは、execute :rake, "taskname" とする必要があると思います。

編集 履歴 (0)
  • お返事ありがとうございます。なるほど、PATHを通す物ではなく、特定のコマンド時だけフルパスで、実行させるものだったんですね。理解不足でした、ありがとうございます。
    ただ実は個々には書いてなかったのですが、unicorn_railsというコマンドを実行したくてRVMのPathを通したかったのです。このコマンドは「.rvm/gems/ruby-1.9.3-p194/bin/」にあるので・・・
    -
  • このGemでは通せなさそうですね。ですが、 SSHKit.config.command_map.prefix[command.to_sym].unshift(rvm_prefix)の辺りを使うと、コマンドを自分で置き換えれそうなので、なんとかできそうですね。ただ、この方法だと恐らく、unicorn_railsとかpryとかを自分でソースに直接書かないと駄目そうです。なんとかこのbin以下にあるもの -
  • を自動で読み込めると楽なのですが、うまい方法はないでしょうか? -
  • bundler をお使いなら `within(current_path){ bundle "exec", "unicorn_rails", ... }` のようにすればいけそうな気がします。 -
ウォッチ

この質問への回答やコメントをメールでお知らせします。