Capistrano is a very nice open source tool for executing commands on one or multiple remote servers via SSH. Capistrano is written in Ruby and uses a rake-like DSL for its tasks. Its main use is to deploy web applications, Rails in particular, but it may be used for much more. Want to try? It’s very easy to getting started.
In a recent project I used Capistrano for building and installing a shared library, written in C. The library had to be built for several platforms on servers with limited Internet access. Before I started using Capistrano I spent several minutes each time just to upload the latest source code, build, and then download the shared library. Of course, it still takes time using Capistrano, but now everything is automated. Even the password input can be automated by using pre-entered passwords (not recommended) or SSH keys. The capfile with the complete task description is actually just a few lines of code.
task :build, :hosts => "email@example.com" do puts %x[svn export trunk] # executing local command - just plain Ruby run "rm -rf my_app" # cleaning up old directory on server upload("my_app", ".", :via => :scp, :recursive => true) # upload source code run "cd my_app;scons" # build on server download("my-app/dist/my_app.so", "remote_build", :via => :scp, :recursive => false) # download built shared library end
Thanks to the simple DSL it should be quite easy to follow the code, even without any Ruby experience. Note that
cd my_app;scons cannot be divided as all commands are executed as
sh -c '<command>' in the user’s home directory by default.
The command to execute the task from terminal is:
cap -p build
-p argument will tell Capistrano to ask for password immediately, rather than waiting for the first remote command. This is quite useful if there are any time-consuming local commands to be executed before the first remote command.
After each build I wanted to install the shared library on all test servers. With Capistrano that was of course very easy – I just added a new target to the capfile.
task :install, :hosts => ["test-host1.example.com", "test-host2.example.com"] do set :user, "johan" # alternative way of setting user run "rm -rf remote_build" # cleaning up old directory upload("remote_build", ".", :via => :scp, :recursive => true) # upload built shared library sudo "cp remote_build/* /usr/lib/my_app/", :pty => true # install as root and with psuedo-tty end
Note that the last command will be executed with psuedo-tty if possible. Normally you will have to have a tty when executing a command with sudo.
Capistrano was really the perfect tool for me in my project. It really saved me a lot of time and needless effort. I hope you too will find it useful.
You can also read my follow-up post on Capistrano – Capistrano and Net:SSH with login shell.