We have a complicated deployment on my current project which includes running several commands as a different user from the main deployment user. Normally, this wouldn’t be a problem since the sudo method provides an option called ‘as’:
task :run_command_as_another_user do sudo "whoami", :as => "another_user" end
Unfortunately, we do not have sudo access to our servers. Instead of using sudo, we wrote a new method called with_user which will execute a block as a different user:
task :try_another_user do with_user("another_user", "another_password") do run "whoami" end end
The with_user method will set the user and password back to the original values once the block is complete. For example:
task :whoami do set :user, 'original' set :password, 'original' run 'whoami' with_user("someone_else", 'password') do run "whoami" end run 'whoami' end
The output of the previous task (stripped down) is:
** [out :: 127.0.0.1] original ** [out :: 127.0.0.1] someone_else ** [out :: 127.0.0.1] original
The implementation of with_user is:
def with_user(new_user, new_pass, &block) old_user, old_pass = user, password set :user, new_user set :password, new_pass close_sessions yield set :user, old_user set :password, old_pass close_sessions end def close_sessions sessions.values.each { |session| session.close } sessions.clear end
It saves the old user and password and then sets the new values. Then, it disconnects from all of the servers, which forces a reconnect on the next command with the new user and password. When the block is complete, it resets the user and password and disconnects again.
The repeated reconnecting is not the most efficient solution, but it is simple and works for us.
3 Responses to “Switching users during a capistrano deploy”
Sorry, the comment form is closed at this time.




Paul, does this mean you have plain text passwords in your capistrano files?
Muness, we do have the passwords in our file, but it is not a big deal for us. Alternatively, you can pass in nil for the password and capistrano will prompt for it. It would be easy to make the password an optional second argument (defaulting to nil).
this is great, it really helped me