Class: PassengerReaper::PassengerProcess

Inherits:
Object
  • Object
show all
Defined in:
lib/passenger_reaper/passenger_process.rb

Constant Summary collapse

MINIMUM_ETIME =

10 minutes

600

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(passenger_status_line) ⇒ PassengerProcess

Returns a new instance of PassengerProcess.



9
10
11
12
13
# File 'lib/passenger_reaper/passenger_process.rb', line 9

def initialize(passenger_status_line)
  values = passenger_status_line.match(/PID:\s(\d*).*Uptime:\s*(.*)$/)
  @pid = values[1].to_i
  @uptime = values[2]
end

Instance Attribute Details

#pidObject

Returns the value of attribute pid.



7
8
9
# File 'lib/passenger_reaper/passenger_process.rb', line 7

def pid
  @pid
end

#uptimeObject

Returns the value of attribute uptime.



7
8
9
# File 'lib/passenger_reaper/passenger_process.rb', line 7

def uptime
  @uptime
end

Class Method Details

.activeObject



28
29
30
31
32
33
34
# File 'lib/passenger_reaper/passenger_process.rb', line 28

def self.active
  passengers = []
  passenger_status.each_line do |line|
    passengers << PassengerProcess.new(line)
  end
  passengers
end

.active_passenger_pidsObject



73
74
75
# File 'lib/passenger_reaper/passenger_process.rb', line 73

def self.active_passenger_pids
  active.map{ |p| p.pid }
end

.all_passenger_pidsObject



85
86
87
88
89
90
91
92
# File 'lib/passenger_reaper/passenger_process.rb', line 85

def self.all_passenger_pids
  passengers = []
  passenger_memory_stats.each_line do |line|
    matcher = line.match(/\s?(\d*)\s/)
    passengers << matcher[1] if matcher
  end
  passengers
end

.inactive_passenger_pidsObject



94
95
96
97
98
99
100
101
102
# File 'lib/passenger_reaper/passenger_process.rb', line 94

def self.inactive_passenger_pids
  inactive_passenger_pids = []
  (all_passenger_pids - active_passenger_pids).each do |pid|
    raw_etime = `ps -p #{pid} --no-headers -o etime`.chomp
    etime = PsEtime.new(raw_etime)
    inactive_passenger_pids << pid unless (etime.age_in_seconds < (MINIMUM_ETIME || 600))
  end
  inactive_passenger_pids
end

.inactive_passengers_last_log_entryObject



139
140
141
142
143
# File 'lib/passenger_reaper/passenger_process.rb', line 139

def self.inactive_passengers_last_log_entry
  inactive_passenger_pids.each do |pid|
    puts last_log_entry(pid)[0, 150]
  end
end

.kill(pid) ⇒ Object



132
133
134
135
136
137
# File 'lib/passenger_reaper/passenger_process.rb', line 132

def self.kill(pid)
  signal = ARGV.include?('--hard') ? 9 : 15
  command = "kill -#{signal} #{pid}"
  puts command
  `#{command}` unless noop?
end

.kill_inactive_passengersObject



114
115
116
117
118
# File 'lib/passenger_reaper/passenger_process.rb', line 114

def self.kill_inactive_passengers
  inactive_passenger_pids.each do |pid|
    kill(pid)
  end
end

.kill_old_passengersObject



120
121
122
123
124
# File 'lib/passenger_reaper/passenger_process.rb', line 120

def self.kill_old_passengers
  old.each do |ps|
    kill(ps.pid)
  end
end

.kill_stale_passengersObject



126
127
128
129
130
# File 'lib/passenger_reaper/passenger_process.rb', line 126

def self.kill_stale_passengers
  stale.each do |p|
    kill(p.pid)
  end
end

.last_log_entry(pid) ⇒ Object



59
60
61
# File 'lib/passenger_reaper/passenger_process.rb', line 59

def self.last_log_entry(pid)
  `grep 'rails\\[#{pid}\\]' #{Dir.pwd}/log/production.log | tail -n 1`.chomp
end

.last_log_entry_time(pid) ⇒ Object



63
64
65
66
67
# File 'lib/passenger_reaper/passenger_process.rb', line 63

def self.last_log_entry_time(pid)
  log_entry = last_log_entry(pid)
  log_entry_time = parse_time_from_log_entry(log_entry)
  (Time.now - log_entry_time).to_i
end

.oldObject



36
37
38
39
40
41
42
43
# File 'lib/passenger_reaper/passenger_process.rb', line 36

def self.old
  passengers = []
  passenger_status.each_line do |line|
    ps = PassengerProcess.new(line)
    passengers << ps if ps.uptime_in_seconds > MINIMUM_ETIME
  end
  passengers
end

.old_passenger_pidsObject



104
105
106
107
108
109
110
111
112
# File 'lib/passenger_reaper/passenger_process.rb', line 104

def self.old_passenger_pids
  old_passenger_pids = []
  all_passenger_pids.each do |pid|
    raw_etime = `ps -p #{pid} --no-headers -o etime`.chomp
    etime = PsEtime.new(raw_etime)
    old_passenger_pids << pid unless (etime.age_in_seconds < (MINIMUM_ETIME || 600))
  end
  old_passenger_pids
end

.parse_time_from_log_entry(entry) ⇒ Object



69
70
71
# File 'lib/passenger_reaper/passenger_process.rb', line 69

def self.parse_time_from_log_entry(entry)
  Chronic.parse(entry.match(/.*\s.*\s\d{1,2}:\d{1,2}:\d{1,2}/)[0])    
end

.passenger_memory_statsObject



77
78
79
80
81
82
83
# File 'lib/passenger_reaper/passenger_process.rb', line 77

def self.passenger_memory_stats
  # 17630  287.0 MB  64.5 MB  Rails: /var/www/apps/gldl/current
  # 17761  285.9 MB  64.9 MB  Rails: /var/www/apps/gldl/current
  # 18242  293.1 MB  71.4 MB  Rails: /var/www/apps/gldl/current
  # 18255  285.9 MB  60.6 MB  Rails: /var/www/apps/gldl/current
  @passenger_memory_stats ||= `passenger-memory-stats | grep 'Rails:.*\/current'`
end

.passenger_statusObject



24
25
26
# File 'lib/passenger_reaper/passenger_process.rb', line 24

def self.passenger_status
  @passenger_status ||= `passenger-status | grep PID`
end

.staleObject



45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/passenger_reaper/passenger_process.rb', line 45

def self.stale
  stale_passengers = []
  potentially_stale_processes = active.select { |p| p.uptime_in_seconds > 600 }
  potentially_stale_processes.each do |process|
    process_last_log_entry = last_log_entry(process.pid)
    etime = (Time.now - parse_time_from_log_entry(process_last_log_entry)).to_i
    if  etime > 600
      puts "Stale process last log entry: #{process_last_log_entry}" if debug?
      stale_passengers << process
    end
  end
  stale_passengers
end

Instance Method Details

#uptime_in_secondsObject



15
16
17
18
19
20
21
# File 'lib/passenger_reaper/passenger_process.rb', line 15

def uptime_in_seconds
  uptime_values = uptime.split(/\s/).map { |u| u.to_i }
  seconds = uptime_values[-1] || 0
  minutes = uptime_values[-2] || 0
  hours = uptime_values[-3] || 0
  seconds + (minutes*60) + (hours*3600)
end