Skip to content

Instantly share code, notes, and snippets.

@aermolaev
Created December 4, 2010 00:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save aermolaev/727779 to your computer and use it in GitHub Desktop.
Save aermolaev/727779 to your computer and use it in GitHub Desktop.
Inspecting Phusion Passenger's status and killing frozen apps
#!/usr/bin/ruby -w
# for passenger 3.0
#
# cron
# */15 * * * * root /root/bin/kill-frozen-passenger-instances
require 'rubygems'
require 'net/http'
require 'uri'
require 'xml'
def main
parse_status(`passenger-status --show=xml`).each do |instance|
if pid = test_instance(instance, '/')
kill_process(pid)
end
end
end
def parse_status(xml)
XML::Document.string(xml).find('//process').map do |process|
data = Proc.new { |xpath|
process.find_first(xpath).content rescue nil
}
if (pid = data['pid']) &&
(password = data['connect_password']) &&
(address = data['server_sockets/server_socket[name = "http"]/address'])
{ :pid => pid.to_i, :password => password, :address => address }
end
end.compact
end
def test_instance(instance, path = '/')
url = URI.parse('http://' + instance[:address])
Net::HTTP.start(url.host, url.port) do |http|
req = Net::HTTP::Get.new(path)
req.add_field('X-Passenger-Connect-Password', instance[:password])
http.open_timeout = 2
http.read_timeout = 2
http.request(req)
end
nil
rescue Timeout::Error
instance[:pid]
rescue => e
puts "#{e.class}: #{e.message}"
nil
end
def kill_process(pid)
begin
10.times do
Process.kill('ABRT', pid)
sleep 0.2
end
rescue Errno::ESRCH
puts "Process with PID #{pid} killed"
end
end
main()
@michaeldv
Copy link

Nice! Any reason for 10.times kill instead of loop? ;-)
Also:
def parse_status(xml)
XML::Document.string(xml).find('//process').map do |process|
data = Proc.new { |xpath| process.find_first(xpath).content rescue nil }

    if (pid      = data['pid']) && 
       (password = data['connect_password']) && 
       (address  = data['server_sockets/server_socket[name = "http"]/address'])
      { :pid => pid.to_i, :password => password, :address => address }
    end
  end.compact
end

@aermolaev
Copy link
Author

Thanks.

Any reason for 10.times kill instead of loop? ;-)

I'm not sure about zombie processes, so make a finite loop.

@michaeldv
Copy link

Понятно :-) Зомбей по идее убивает Process.kill('KILL', pid) или sudo kill -9 #{pid}

@aermolaev
Copy link
Author

Не, зомби по определению уже не живой, поэтому убивать нечего ;) Можно убить родителя, но в данном случае как-то не хочется )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment