Using Capistrano

 in
“We will encourage you to develop the three great virtues of a programmer: laziness, impatience, and hubris.”—Larry Wall, Programming Perl
Finding More

To deploy our application, we used only deploy:setup, deploy:cold and deploy. The recipe has a lot more in it. To see all the available tasks, run:

cap -Tv

Much like rake -T, this lists all the tasks with their documentation. If you've run deploy a few times, play with either of the rollback or rollback_code tasks.

Each time you roll back, Capistrano simply points the symlink to the previous deployment's directory. Rollbacks can be run repeatedly until you find the stable version you want:

cap deploy:rollback_code

Your Own Tasks

Once you get Capistrano working on a Rails project, it's easy to see how it could help make your life really lazy. The same kind of tasks that wrap around Rails-specific commands can contain pretty much any command.

When you run Capistrano tasks, like deploy, you'll see various SSH commands and responses scroll by. If you have several servers, the responses will come back from multiple servers as Capistrano runs your tasks across as many machines as you need.

The potential uses of this are huge—checking disk space, copying live data from clusters and running maintenance tasks—so how can we build our own tasks?

Tasks in Capistrano are defined with the following syntax:

desc "Short description here..."
task :name_of_function, :roles => :servers do
        # tasks is in here...
end

Ruby's elegant syntax often makes things confusingly simple, so let's pick it apart. The first line provides some documentation that is output when you run the following on the command line (still from the root of your project):

cap -Tv

Ruby can cope without brackets when calling functions, so the second line actually is a call to Capistrano's task function.

The first argument is the new task's name (name_of_function). The second is the set of machines on which the task will be run; this can be either :servers, :app, :db or any other collection of servers you have.

The last part, starting at do, is an anonymous function, which means that everything between do and end is executed when your task is run. You may have come across anonymous functions in JavaScript.

A very simple task would be to run df -h on the remote servers to check on disk space. This isn't going to change anything on your servers, so you should feel safe running it:

desc "Check disk space"
task :diskspace, :roles => :servers do
        run 'df -h'
end

The run function simply runs the command on the remote servers. You can replace this with sudo, which also does what it sounds like—runs remote commands under sudo:

desc "Who hasn't been cleaning out their home directories?"
task :home_disk_usage, :roles => :servers do
        sudo 'du -sh /home/*'
end

If you have capified a project as we did on the Rails project in the previous section, you even can add your own custom tasks to the standard Rails recipe and change the behaviour of the Rails recipe itself. This lets you get Capistrano working just as you need it to work, and it's is good for those commands you never can remember how to run!

To add your own tasks to a capified Rails project, add them to config/deploy.rb using the task syntax described above. Once you have added a task, run cap -Tv to check whether your task was found, and then run the task as you would any other.

Tasks can call each other just like functions can, so complex tasks can be broken down into simple tasks that will keep your custom Capistrano recipes “DRY”. Tasks can call each other using the normal Rails function call:

task :home_disk_usage, :roles => :servers do
        vhosts_disk_usage
        run "ls /home/"
end

You'll probably want your customised tasks to know the location in the filesystem where your project is being deployed. This is a matter of using the configuration variables we set right at the beginning, which can be done using the Ruby syntax:

run "tar czf ~/snapshot.tgz #{release_path}"

If you need additional variables, you can set them using the same syntax as before:

set :foo, "bar"

Alternatively, you can prompt the user for the variables by using the set function, but with a slightly different usage:

set(:deploy_version) do
        Capistrano::CLI.ui.ask "What version is this? "
end

The variables are used in the same way, no matter which method is used to set them.

All this Ruby should start falling into place, and by this point, you'll start thinking of Capistrano as a Ruby framework rather than a standalone application or script. If Ruby is new to you, keep going—it'll start dropping into place soon.

Finally, it's nice to keep things neat as well as DRY. All of the Rails recipes are found in the deploy namespace, which you'll notice when you run cap -Tv. Namespaces allow you to group tasks together, and this can be done by wrapping the tasks in the namespace command:

namespace :our_tasks do
  desc "The default task"
  task :default do
    restart
end
  
  desc "Empty logs"
  task :empty_logs do
        # ...
  end
end

When you run cap -Tv, you'll see these neatly grouped:

cap our_tasks            # The default task
cap our_tasks:empty_logs # Empty logs

______________________

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

cap'ing Rails projects on servers

Walther Diechmann's picture

Hi Dan,

nice article - do you have any 'advanced' setups, like this one?

role :app, "10.4.3.223", :primary => true, :user => "root"
role :web, "10.4.3.221"
role :db, "10.4.3.220"
set :gateway, "webserver.domain.tld"

set :repository, "git@10.4.3.222:#{application}.git"

why?

Because I cannot get my multistage deploy to work :)

All the blogs and articles I've come around, they all seem to focus on setups with all servers on one machine, and git somewhere entirely else (like github.com)

Best regards,
Walther

White Paper
Linux Management with Red Hat Satellite: Measuring Business Impact and ROI

Linux has become a key foundation for supporting today's rapidly growing IT environments. Linux is being used to deploy business applications and databases, trading on its reputation as a low-cost operating environment. For many IT organizations, Linux is a mainstay for deploying Web servers and has evolved from handling basic file, print, and utility workloads to running mission-critical applications and databases, physically, virtually, and in the cloud. As Linux grows in importance in terms of value to the business, managing Linux environments to high standards of service quality — availability, security, and performance — becomes an essential requirement for business success.

Learn More

Sponsored by Red Hat

White Paper
Private PaaS for the Agile Enterprise

If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.

Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.

Learn More

Sponsored by ActiveState