Sha256: fae9c8b9b23898fcf1a483abe82a1365fe1ee005d4e257ee1c4f672412a65c45

Contents?: true

Size: 1.96 KB

Versions: 1

Compression:

Stored size: 1.96 KB

Contents

class ZombiePassengerKiller
  VERSION = File.read( File.join(File.dirname(__FILE__),'..','VERSION') ).strip

  def initialize(options)
    @history = {}
    @history_entries = options[:history] || 5
    @max_high_cpu = options[:max]
    @high_cpu = options[:cpu] || 70
    @grace_time = options[:grace] || 5
    @interval = options[:interval] || 5
    @pattern = options[:pattern] || ' Rack: '
  end

  def store_current_cpu(processes)
    keys_to_remove = @history.keys - processes.map{|x| x[:pid] }
    keys_to_remove.each{|k| !@history.delete k }

    processes.each do |process|
      @history[process[:pid]] ||= []
      @history[process[:pid]] << process[:cpu]
      @history[process[:pid]] = @history[process[:pid]].last(@history_entries)
    end
  end

  def get_strace(pid, time)
    %x(timeout #{time} strace -p #{pid} 2>&1) if system("which timeout > /dev/null")
  end

  def hunt_zombies
    active_pids_in_passenger_status = passenger_pids
    active_processes_in_processlist = process_status
    zombies = active_processes_in_processlist.map{|x| x[:pid] } - active_pids_in_passenger_status

    # kill processes with high CPU if user wants it
    high_load = if @max_high_cpu
      store_current_cpu active_processes_in_processlist
      active_pids_in_passenger_status.select do |pid|
        @history[pid].count{|x| x > @high_cpu } >= @max_high_cpu
      end
    else
      []
    end

    (high_load + zombies).each do |pid|
      kill_zombie pid
    end
  end

  def passenger_pids
    %x(passenger-status|grep PID).split("\n").map{|x| x.strip.match(/PID: \d*/).to_s.split[1]}.map(&:to_i)
  end

  def process_status
    %x(ps -eo pid,pcpu,args|grep -v grep|grep '#{@pattern}').split("\n").map do |line|
       values = line.strip.split[0..1]
       {:pid => values.first.to_i, :cpu => values.last.to_f}
    end
  end

  def kill_zombie(pid)
    puts "Killing passenger process #{pid}"
    puts get_strace(pid, 5)
    puts %x(kill #{pid})
    sleep @grace_time
    %x(kill -9 #{pid})
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
zombie_passenger_killer-0.1.0 lib/zombie_passenger_killer.rb