Capistrano and the shell used for run

A short blog post in lieu of a longer one, since I’m so busy. However I noticed this recently and figured someone else might be wondering.

The workflow for my biggest client involves using Jenkins as a coordinator for builds & deploys. This often involves checking out something from git, running tests and whatever, then using Capistrano to deploy it (we generally use Capistrano even if the project isn’t Ruby, unless it comes with something else).

While working on a python project recently, using virtualenv, I noticed that I couldn’t use source in a run command:

* executing `app:pip'
  * executing "cd /mnt/web_stage/sites/someclient.com/web-app/releases/20120430160812 && source someclient/bin/activate && pip install -r requirements/requirements.txt"
    servers: ["localhost"]
    [localhost] executing command
*** [err :: localhost] sh: source: not found

Err…sh?

Turns out, by default, Capistrano won’t send the command itself directly, such as:

ssh foo@bar 'cap production deploy'

but rather attempts to make any potential shell differences irrelevant, and uses:

ssh foo@bar 'sh -c 'cap production deploy' '

…opting for the lowest common denominator, sh. Which is fine, but not helpful for what I was trying to do (install stuff in a virtualenv environment, for which source is useful).

You can change this by setting :shell to be either false (to execute commands directly) or a path to a shell you prefer.

Interestingly, setting this is not intuitive. Trying to set this as you might expect:

set :shell, false

does absolutely nothing.

After looking through the gem source, I found that this works:

default_run_options[:shell] = false

That allowed me to source the activation script for virtualenv, and then everything works as you might expect.

Also, please, don’t give me any jibba jabba about how I’m not using Fabric. We decided on a standard and we use the standard.

4 Replies to “Capistrano and the shell used for run”

  1. Could you point me to where you add that statement? I tried adding it in my capfile and in the deploy.rb but I get a “local variable not found” error. In what scope is that symbol/variable defined?

    1. You should just be able to put it in your Capfile, or in your environment specific file. That’s where I put it; granted this was with Capistrano 2.

Leave a Reply

Your email address will not be published. Required fields are marked *