Capistrano: Executing a command as root without using sudo

July 27th, 2010 at 1:20 pm • permalink3 comments

I don’t have time to read and I want to jump immediately to the solution →.

The problem

Capistrano LogoFrom the day I started using DelayedJob in combination with God, I faced the problem to restart the god group every time I deployed a new application release.

In fact, when a rake task (God runs DelayedJob using the rake jobs:work task, here’s the config) is started, it loads the entire Rails environment and keeps it in memory as long as the process is running. When you deploy a new version, if you don’t restart the rake task, DelayedJob continues to run with the previous Rails version environment.

To restart a task/group in God:

1
$ god restart GROUP_NAME

Speaking about my servers, the problem is that God runs as root while Capistrano deploys new releases using a not-root not-sudo user, for security purposes. In practice, it means I can’t use the Capistrano sudo command because the deploy user is not in the sudoers list. Fortunately, the solution exists and is to run the command as su -c <command>.

The gotcha here is that when you use su you have to handle the remote server root password prompt. Thanks to Capistrano, this is as easy as pie.

Here’s the method I created to run the command.

The solution

1
2
3
4
5
6
7
8
9
10
11
12
13
# Runs +command+ as root invoking the command with su -c
# and handling the root password prompt.
#
#   surun "/etc/init.d/apache reload"
#   # Executes
#   # su - -c '/etc/init.d/apache reload'
#
def surun(command)
  password = fetch(:root_password, Capistrano::CLI.password_prompt("root password: "))
  run("su - -c '#{command}'") do |channel, stream, output|
    channel.send_data("#{password}n") if output
  end
end

And here’s the final Capistrano/DelayedJob/Run code fragment.

1
2
3
4
5
6
7
8
namespace :god do
  desc "Restart the god group 'GROUP_NAME'"
  task :restart, :roles => :app do
    surun "god restart GROUP_NAME"
  end
end

after "deploy:restart", "delayed_job:restart"
  1. How to restart God when you deploy a new release via Capistrano
  2. Running Capistrano with Passenger (mod_rails)
  3. Capistrano and database.yml
  4. Capistrano: Managing an uploads folder
  5. Capistrano: File Transfer actions

Filed in Programming • Tags: , , , , , , ,

Comments

kaczor1984 says:

Is there everything ok with surun? I got `surun’: undefined method `password_prompt’ for # (NoMethodError).

I`ve checked in the cli/ui.rb and Capistrano::CLI.password_prompt… without ‘ui’ works for me.

Unfortunately on Debian i get ‘su: must be run from a terminal’.
On my way to find the solution then.

You’re right kaczor1984, the method should be invoked on CLI.
I updated the example, thank you.

[...] release? I already discussed this problem in the past and the solution I adopted since today was to execute a command as root without using sudo. The problem with this solution, is that it requires you to type the root password each time you [...]

Add a Comment




Follow Me
    Random Quote