namespace :remix do # Returns true if the indicated server has any file uploads going def file_upload_in_progress?(server) uploads = `ssh #{server} 'ls -ltr /tmp'`.grep(/mongrel/) uploads.each do |upload| # See if timestamp is recent if upload =~ /([A-Za-z]+ \d\d \d+:\d+)/ time = Time.parse($1) if time > (Time.now - 3.minutes) puts "Current upload: #{upload}" return true else puts "Old upload: #{upload}" end end end false end # Updates subversion on the indicated server, and returns an array of # conflicts if there were any, or else an empty array. def svn_up(server, dir_list = "") result = `ssh #{server} 'cd /home/rails/svn/myapp; svn up #{dir_list}'`.split("\n") conflicts = result.grep(/^C/) return result, conflicts end def run_sudo(cmd, password) puts "Trying sudo password: #{password}" IO.popen("sudo -S #{cmd}", "r+") do |io| io.puts(password) puts io.readlines end end def remote_sudo(server, cmd, password) puts "[sudo, #{server}] #{cmd}" result = "" IO.popen("ssh -T #{server}", "r+") do |io| io.puts("sudo -S #{cmd}") io.puts(password) io.puts("sudo -k") io.close_write result = io.readlines end result end def prompt(msg) print msg STDIN.readline end def prompt_password prompt("Enter sudo password: ") end def restart_web(server, password) puts remote_sudo(server, "apachectl stop", password) puts "[ssh] restart mongrel cluster" result = `ssh #{server} 'cd /home/rails/svn/myapp; mongrel_rails cluster::restart --clean; rm -f /tmp/*'`.split("\n") puts result.join("\n") puts remote_sudo(server, "apachectl start", password) end def update_and_restart_web(server, password) puts "[1 - #{server}] Check for uploads in progress" if file_upload_in_progress?(server) puts "active upload - can't update" else puts "[2 - #{server}] Update subversion" result, conflicts = svn_up(server) if conflicts.size > 0 puts "ERROR!! File conflicts:" puts conflicts.join("\n") else puts result.join("\n") puts "[3 - #{server}] Restart mongrels and apache" restart_web(server, password) end end end desc "Update svn and restart web1" task :update_web1 do update_and_restart_web("web1", prompt_password()) end desc "Update svn and restart web2" task(:update_web2 => :environment) do update_and_restart_web("web2", prompt_password()) end desc "Update svn and restart web3" task(:update_web3 => :environment) do update_and_restart_web("web3", prompt_password()) end desc "Check that all webs can be updated" task(:check_web_update => :environment) do puts "[web1] Check for uploads in progress" if file_upload_in_progress?("web1") puts "WEB1 has uploads!" end puts "[web2] Check for uploads in progress" if file_upload_in_progress?("web2") puts "WEB2 has uploads!" end puts "[web3] Check for uploads in progress" if file_upload_in_progress?("web3") puts "WEB3 has uploads!" end end desc "Subversion update and restart all webs" task(:update_all_webs => [:environment,:check_web_update]) do puts "paused. Hit enter to continue..." STDIN.readline password = prompt_password update_and_restart_web("web1", password) prompt("\nUpdate web2?") update_and_restart_web("web2", password) prompt("\nUpdate web3?") update_and_restart_web("web3", password) end desc "Update public from subversion on all web servers" task(:update_svn_view => :environment) do puts "Updating web1" result, conflicts = svn_up("web1", "public app/views") puts result.join("\n") puts "Updating web2" result, conflicts = svn_up("web2", "public app/views") puts result.join("\n") puts "Updating web3" result, conflicts = svn_up("web3", "public app/views") puts result.join("\n") end end