53

I have a basic Rails 3 app working locally on my development box, but want to test out deploying early on to make sure everything works. I'm using Capistrano to deploy.

When I run cap deploy (after all the other necessary setup), it breaks on this command with this error:

[...]
* executing 'bundle:install'
* executing "bundle install --gemfile /var/www/trex/releases/20100917172521/Gemfile --path /var/www/trex/shared/bundle --deployment --quiet --without development test"

servers: ["www.[my domain].com"]
[www.[my domain].com] executing command
** [out :: www.[my domain].com] sh: bundle: command not found
command finished
[...]

So it looks like it can't find the bundle command on the server.

However, when I log in to the server...

$ ruby -v
ruby 1.9.2p0 (2010-08-18 revision 29036) [x86_64-linux]
$ rails -v
Rails 3.0.0
$ bundle -v
Bundler version 1.0.0

...the bundle command works just fine.

What could be going wrong?

-

(Furthermore, for completeness:)

$ which ruby
~/.rvm/rubies/ruby-1.9.2-p0/bin/ruby
$ which rails
~/.rvm/gems/ruby-1.9.2-p0/bin/rails
$ which bundle
~/.rvm/gems/ruby-1.9.2-p0/bin/bundle
T.J. Schuck
  • 3,645
  • 2
  • 19
  • 20

8 Answers8

89

UPDATE:

For RVM >= 1.11.3, you should now just use the rvm-capistrano gem. For older RVM >= 1.0.1, the answer below still applies.


ORIGINAL ANSWER:

Okay, though I still haven't gotten a full cap deploy to work, I did fix this problem. The problem was Capistrano trying to use a different path for Bundler (and other gems) than the RVM paths.

Check your Capistrano path by doing cap shell, then echo $PATH. You'll probably see your standard /usr/local/bin and /usr/bin, but that's not where RVM has Bundler, et al., stored.

Edit your Capistrano config/deploy.rb file, and add the following lines, per these instructions:

# Add RVM's lib directory to the load path.
$:.unshift(File.expand_path('./lib', ENV['rvm_path']))

# Load RVM's capistrano plugin.    
require "rvm/capistrano"

set :rvm_ruby_string, '1.9.2'
set :rvm_type, :user  # Don't use system-wide RVM

That finally got Capistrano to see Bundler and start loading gems appropriately.

T.J. Schuck
  • 3,645
  • 2
  • 19
  • 20
  • 1
    I have rvm installed system wide and deploying with local user. To make it work I have to be sure that the user from which I am deploying have setuped the rvm right. The .bashrc troubleshooting described http://rvm.beginrescueend.com/rvm/install/ here helped – Ivailo Bardarov Jan 31 '11 at 19:01
  • 1
    Maybe you'll find yourself here if you tried to upgrade the rvm capistrano integration from what is listed here: http://ariejan.net/2011/09/14/lighting-fast-zero-downtime-deployments-with-git-capistrano-nginx-and-unicorn?utm_source=rubyweekly&utm_medium=email to the new approach mentioned in this answer. If you do remove the `default_environment` lines be sure to also remove `default_run_options[:shell] = 'bash'` otherwise you still won't have rvm on the capistrano shell. – Brendon Muir Sep 28 '11 at 01:53
  • That does not work for me. Only that works: set :bundle_cmd, 'source $HOME/.bash_profile && bundle' – hipertracker Nov 27 '11 at 03:41
  • 2
    This has changed, some time recently. You can now just do gem install rvm-capistrano to solve the issue – hrdwdmrbl May 29 '12 at 14:24
  • This will give you a warning now: RVM - Capistrano integration was extracted to a separate gem, install: `gem install rvm-capistrano` and remove the `$LOAD_PATH.unshift` line – Snowcrash Jun 20 '13 at 19:59
  • @jackquack -- the answer is now updated for newer versions of RVM. – T.J. Schuck Jun 25 '13 at 18:48
26

Bundler isn't found because .bash_profile is not being loaded and thus your PATH is wrong. This is probably because you have the RVM script in .bash_profile.

The simple answer is to move the RVM script from .bash_profile to .bashrc and Capistrano should be able to find it (also verify that .bash_profile sources .bashrc).

Capistrano uses SSH to execute commands on the server via a non-interactive shell. This shell session will source .bashrc but not .bash_profile. I added an ECHO statement to both and ran an LS via SSH. You can see in the results below that only .bashrc is sourced:

$ ssh user@123.amazonaws.com ls
.bashrc loaded
git
file1
file2
Community
  • 1
  • 1
Pete Campbell
  • 301
  • 3
  • 2
  • Is it a good practice to always source your `.bash_profile` from your `.bashrc` ? That way your `.bash_profile` always gets sourced no matter whether it's an interactive or non-interactive shell – user2490003 Jun 10 '15 at 22:11
11

I had an identical problem using rbenv. The solution was to take the rbenv specific lines from the bottom of my .bashrc file and put them at the top. The first line of my .bashrc file was returning aborting if the shell wasn't running in interactive mode.

Lelon
  • 905
  • 1
  • 8
  • 15
7

That last line should actually be

set :rvm_type, :user

that is, user must be a symbol and not a variable, otherwise you'll get

undefined local variable or method `user'
RussK
  • 93
  • 2
  • 6
7

No rvm/capistrano worked for me. The best solution I found was adding to deploy.rb file the following line (it's for non system-wide RVM):

set :bundle_cmd, 'source $HOME/.bash_profile && bundle'

hipertracker
  • 2,425
  • 26
  • 16
2

It was my understanding that the bundle command is not found because the PATH variable, defined in the user's ~/.bash_profile, isn't loaded by Capistrano.

To get around this I have created a task :bundle_gems.

task :bundle_gems do
    run "cd #{deploy_to}/current && export PATH=/usr/local/pgsql/bin:/opt/ruby-enterprise-X.X.X/bin:$PATH && bundle install vendor/gems"
end

Note that I also include the path to PostgreSQL binaries - installation of the pg gem was failing because they could not be found, even when bundle could be found.

This seems like a messy approach, though. Presumably there is a more 'global' place to define paths to binaries that I don't know about.

Update 23/12

To add a directory to $PATH for all users: https://serverfault.com/questions/102932/adding-a-directory-to-path-in-centos

However this still won't be loaded because it is a non-interactive non-login shell.

One suggestion was to add the paths to /etc/bashrc: How do I set $PATH such that `ssh user@host command` works?

However this also didn't work for me. I believe its because SSH doesn't load /etc/bashrc either.

Another suggestion was to edit ~/.ssh/environment: http://www.ruby-forum.com/topic/79248. However this seems almost as messy as specifying the paths in deploy.rb.

Community
  • 1
  • 1
Sai Perchard
  • 853
  • 1
  • 10
  • 12
1

This one worked for me:

set :bundle_cmd, 'source $HOME/.bash_profile && bundle'

Nesha Zoric
  • 6,218
  • 42
  • 34
0

I tried a number of the suggestions. Had problems with setting the paths in the deploy.rb file for the RVM environment. My final solution was to include the following:

In the config/deploy.rb file add:

require "bundler/capistrano"

Also in config/deploy.rb, or in my case config/production.rb as I was using the multistage option for Capistrano

after "deploy", "rvm:trust_rvmrc"

This step simply ensures that we stop getting the 'do you want to trust the .rvmrc file' and it calls a task in the deploy.rb file such as:

namespace :rvm do
   task :trust_rvmrc do
      run "rvm rvmrc trust #{release_path}"
   end
end

After putting in these slight changes I was able to run cap production deploy which checked out the code; executed the asset pipeline deployment, linked up the release folder to current, executed bundle install and cleaned up.

Grant Sayer
  • 2,330
  • 1
  • 23
  • 34