module RailsPwnerer::Util
Public Class Methods
kill_process_set(kill_script, pid_patterns, process_patterns, options = {})
click to toggle source
Complex procedure for killing a process or a bunch of process replicas kill_command is the script that’s supposed to kill the process / processes (tried first) pid_patters are globs identifying PID files (a file can match any of the patterns) process_patterns are strings that should show on a command line (a process must match all)
options:
:verbose - display what gets killed :script_delay - the amount of seconds to sleep after launching the kill script :force_script - the kill script is executed even if there are no PID files
# File lib/rails_pwnerer/util/kill_process_set.rb 12 def self.kill_process_set(kill_script, pid_patterns, process_patterns, options = {}) 13 # Phase 1: kill order (only if there's a PID file) 14 pid_patterns = [pid_patterns] unless pid_patterns.kind_of? Enumerable 15 unless options[:force_script] 16 pid_files = pid_patterns.map { |pattern| Dir.glob(pattern) }.flatten 17 end 18 if options[:force_script] or !(pid_files.empty? or kill_script.nil?) 19 print "Issuing kill order: #{kill_script}\n" if options[:verbose] 20 success = Kernel.system kill_script unless kill_script.nil? 21 if !success and options[:verbose] 22 print "Kill order failed with exit code #{$CHILD_STATUS.exitstatus}\n" 23 end 24 25 deadline_time = Time.now + (options[:script_delay] || 0.5) 26 while Time.now < deadline_time 27 pid_files = pid_patterns.map { |pattern| Dir.glob(pattern) }.flatten 28 break if pid_files.empty? 29 sleep 0.05 30 end 31 end 32 33 # Phase 2: look through PID files and issue kill orders 34 pinfo = process_info() 35 pid_files = pid_patterns.map { |pattern| Dir.glob(pattern) }.flatten 36 pid_files.each do |fname| 37 begin 38 pid = File.open(fname, 'r') { |f| f.read.strip! } 39 process_cmdline = pinfo[pid][:cmdline] 40 # avoid killing innocent victims 41 if pinfo[pid].nil? or process_patterns.all? { |pattern| process_cmdline.index pattern } 42 print "Killing #{pid}: #{process_cmdline}\n" if options[:verbose] 43 kill_tree pid.to_i 44 end 45 rescue 46 # just in case the file gets wiped before we see it 47 end 48 begin 49 print "Deleting #{fname}\n" if options[:verbose] 50 File.delete fname if File.exists? fname 51 rescue 52 # prevents crashing if the file is wiped after we call exists? 53 end 54 end 55 56 # Phase 3: look through the process table and kill anything that looks good 57 pinfo = process_info() 58 pinfo.each do |pid, info| 59 next unless process_patterns.all? { |pattern| info[:cmdline].index pattern } 60 print "Killing #{pid}: #{pinfo[pid][:cmdline]}\n" if options[:verbose] 61 kill_tree pid.to_i 62 end 63 end