zombie_passenger_killer 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Readme.md +14 -8
- data/bin/zombie_passenger_killer +1 -0
- data/lib/zombie_passenger_killer/reaper.rb +12 -6
- data/lib/zombie_passenger_killer/version.rb +1 -1
- metadata +8 -23
- data/.travis.yml +0 -4
- data/Gemfile +0 -6
- data/Gemfile.lock +0 -28
- data/Rakefile +0 -6
- data/spec/spec_helper.rb +0 -1
- data/spec/zombie_passenger_killer_spec.rb +0 -186
- data/zombie_passenger_killer.gemspec +0 -12
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5780e6196f2270301870a5859bf75a2ab43da51a
|
4
|
+
data.tar.gz: 032a0875bb8d4bffd797b1aadb9bb2b21ce17c1e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 90d28d0ff5cca9d60b208a757f99bed45739a197ea920cd9032680a1b284b3fab8654c657508851fac4a8361d0dcf61e82666211b86a4f13ec4a095099e9cabb
|
7
|
+
data.tar.gz: c0f70fa2e121e6e7044b8dc99fcd81f1e47c2bcc433190b65566c31e9e9e7672e0da7abe78eadfecf98df30b82c777acccd8f77a09f799d58d6bf50ed75185bb
|
data/Readme.md
CHANGED
@@ -13,7 +13,10 @@ Add passenger-status to `/etc/sudoers` or run with sudo.
|
|
13
13
|
|
14
14
|
Install
|
15
15
|
=======
|
16
|
-
|
16
|
+
|
17
|
+
```
|
18
|
+
sudo gem install zombie_passenger_killer
|
19
|
+
```
|
17
20
|
|
18
21
|
Usage
|
19
22
|
=====
|
@@ -36,12 +39,14 @@ Usage
|
|
36
39
|
|
37
40
|
### Bluepill script
|
38
41
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
42
|
+
```Ruby
|
43
|
+
app.process("zombie_passenger_killer") do |process|
|
44
|
+
process.start_command = "zombie_passenger_killer --max 5 --history 10 --cpu 30 --interval 10"
|
45
|
+
process.stdout = process.stderr = "/var/log/autorotate/zombie_passenger_killer.log"
|
46
|
+
process.pid_file = "/var/run/zombie_passenger_killer.pid"
|
47
|
+
process.daemonize = true
|
48
|
+
end
|
49
|
+
```
|
45
50
|
|
46
51
|
### Monit script
|
47
52
|
|
@@ -62,9 +67,10 @@ Author
|
|
62
67
|
- [Roman Heinrich](https://github.com/mindreframer)
|
63
68
|
- [Kevin Mullin](https://github.com/kmullin)
|
64
69
|
- [Valery Vishnyakov](https://github.com/balepc)
|
70
|
+
- [Bodo Tasche](https://github.com/bitboxer)
|
65
71
|
|
66
72
|
[Michael Grosser](http://grosser.it)<br/>
|
67
73
|
michael@grosser.it<br/>
|
68
74
|
License: MIT<br/>
|
69
|
-
[![Build Status](https://
|
75
|
+
[![Build Status](https://travis-ci.org/grosser/zombie_passenger_killer.png)](https://travis-ci.org/grosser/zombie_passenger_killer)
|
70
76
|
|
data/bin/zombie_passenger_killer
CHANGED
@@ -22,6 +22,7 @@ BANNER
|
|
22
22
|
opts.on("-i", "--interval [SECONDS]", Integer, "Check every SECONDS (default: 10)") {|i| options[:interval]=i }
|
23
23
|
opts.on("-p", "--pattern [PATTERN]", String, "Find processes with this pattern (default: ' Rack: ')") {|i| options[:pattern]=i }
|
24
24
|
opts.on("-1", "--once", "Check once and exit") { options[:once]=true }
|
25
|
+
opts.on("--verbose", "Verbose") { options[:verbose] = true }
|
25
26
|
opts.on("--rvmsudo", "Use `rvmsudo` to see passenger-status") { options[:rvmsudo]=true }
|
26
27
|
opts.on("-h", "--help","Show this") { puts opts; exit }
|
27
28
|
opts.on("-v", "--version","Show Version"){ puts version; exit }
|
@@ -12,6 +12,7 @@ module ZombiePassengerKiller
|
|
12
12
|
@pattern = options[:pattern] || ' Rack: '
|
13
13
|
@show_times = options[:show_times] || false
|
14
14
|
@interval = options[:interval] || 10
|
15
|
+
@verbose = options[:verbose]
|
15
16
|
@strace_time = 5
|
16
17
|
@out = STDOUT
|
17
18
|
@rvmsudo = options[:rvmsudo]
|
@@ -29,8 +30,13 @@ module ZombiePassengerKiller
|
|
29
30
|
|
30
31
|
def hunt_zombies
|
31
32
|
active_pids_in_passenger_status = passenger_pids
|
33
|
+
puts "Active pids in status: #{active_pids_in_passenger_status.inspect}" if @verbose
|
34
|
+
|
32
35
|
active_processes_in_processlist = process_status
|
36
|
+
puts "Active pids in processlist: #{active_processes_in_processlist.inspect}" if @verbose
|
37
|
+
|
33
38
|
zombies = active_processes_in_processlist.map{|x| x[:pid] } - active_pids_in_passenger_status rescue Array.new
|
39
|
+
puts "Zombies: #{zombies.inspect}" if @verbose
|
34
40
|
|
35
41
|
# kill processes with high CPU if user wants it
|
36
42
|
high_load = if @max_high_cpu
|
@@ -65,10 +71,10 @@ module ZombiePassengerKiller
|
|
65
71
|
`( strace -p #{pid} 2>&1 ) & sleep #{time} ; kill $! 2>&1`
|
66
72
|
end
|
67
73
|
|
68
|
-
# return array of pids reported from passenger-status command, nil if passenger
|
74
|
+
# return array of pids reported from passenger-status command, nil if passenger doesn't run
|
69
75
|
def passenger_pids
|
70
|
-
pids = %x(#{'rvmsudo ' if @rvmsudo}passenger-status
|
71
|
-
if $?.
|
76
|
+
pids = %x(#{'rvmsudo ' if @rvmsudo}passenger-status).split("\n").map { |l| l[/PID: (\d+)/, 1] }.compact.map(&:to_i)
|
77
|
+
if $?.success?
|
72
78
|
pids
|
73
79
|
else
|
74
80
|
raise "passenger-status returned a #{$?.exitstatus} exit code. Please check if passenger-status is working properly."
|
@@ -76,9 +82,9 @@ module ZombiePassengerKiller
|
|
76
82
|
end
|
77
83
|
|
78
84
|
def process_status
|
79
|
-
%x(ps -eo pid,pcpu,args|grep -v grep|egrep '#{@pattern}').split("\n").map do |line|
|
80
|
-
|
81
|
-
|
85
|
+
%x(ps -eo pid,pcpu,args|grep -v grep|grep -v zombie_passenger_killer|egrep '#{@pattern}').split("\n").map do |line|
|
86
|
+
values = line.strip.split[0..1]
|
87
|
+
{:pid => values.first.to_i, :cpu => values.last.to_f}
|
82
88
|
end
|
83
89
|
end
|
84
90
|
|
metadata
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zombie_passenger_killer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
version: 0.3.0
|
4
|
+
version: 0.3.1
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Michael Grosser
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-12-04 00:00:00.000000000 Z
|
13
12
|
dependencies: []
|
14
13
|
description:
|
15
14
|
email: michael@grosser.it
|
@@ -18,47 +17,33 @@ executables:
|
|
18
17
|
extensions: []
|
19
18
|
extra_rdoc_files: []
|
20
19
|
files:
|
21
|
-
- .travis.yml
|
22
|
-
- Gemfile
|
23
|
-
- Gemfile.lock
|
24
|
-
- Rakefile
|
25
20
|
- Readme.md
|
26
21
|
- bin/zombie_passenger_killer
|
27
22
|
- lib/zombie_passenger_killer.rb
|
28
23
|
- lib/zombie_passenger_killer/reaper.rb
|
29
24
|
- lib/zombie_passenger_killer/version.rb
|
30
|
-
|
31
|
-
- spec/zombie_passenger_killer_spec.rb
|
32
|
-
- zombie_passenger_killer.gemspec
|
33
|
-
homepage: http://github.com/grosser/zombie_passenger_killer
|
25
|
+
homepage: https://github.com/grosser/zombie_passenger_killer
|
34
26
|
licenses:
|
35
27
|
- MIT
|
28
|
+
metadata: {}
|
36
29
|
post_install_message:
|
37
30
|
rdoc_options: []
|
38
31
|
require_paths:
|
39
32
|
- lib
|
40
33
|
required_ruby_version: !ruby/object:Gem::Requirement
|
41
34
|
requirements:
|
42
|
-
- -
|
35
|
+
- - ">="
|
43
36
|
- !ruby/object:Gem::Version
|
44
37
|
version: '0'
|
45
|
-
segments:
|
46
|
-
- 0
|
47
|
-
hash: 91186768020065310
|
48
|
-
none: false
|
49
38
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
39
|
requirements:
|
51
|
-
- -
|
40
|
+
- - ">="
|
52
41
|
- !ruby/object:Gem::Version
|
53
42
|
version: '0'
|
54
|
-
segments:
|
55
|
-
- 0
|
56
|
-
hash: 91186768020065310
|
57
|
-
none: false
|
58
43
|
requirements: []
|
59
44
|
rubyforge_project:
|
60
|
-
rubygems_version:
|
45
|
+
rubygems_version: 2.2.2
|
61
46
|
signing_key:
|
62
|
-
specification_version:
|
47
|
+
specification_version: 4
|
63
48
|
summary: Guaranteed zombie passengers death
|
64
49
|
test_files: []
|
data/.travis.yml
DELETED
data/Gemfile
DELETED
data/Gemfile.lock
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
zombie_passenger_killer (0.3.0)
|
5
|
-
|
6
|
-
GEM
|
7
|
-
remote: http://rubygems.org/
|
8
|
-
specs:
|
9
|
-
bump (0.3.9)
|
10
|
-
diff-lcs (1.1.3)
|
11
|
-
rake (0.9.2)
|
12
|
-
rspec (2.6.0)
|
13
|
-
rspec-core (~> 2.6.0)
|
14
|
-
rspec-expectations (~> 2.6.0)
|
15
|
-
rspec-mocks (~> 2.6.0)
|
16
|
-
rspec-core (2.6.4)
|
17
|
-
rspec-expectations (2.6.0)
|
18
|
-
diff-lcs (~> 1.1.2)
|
19
|
-
rspec-mocks (2.6.0)
|
20
|
-
|
21
|
-
PLATFORMS
|
22
|
-
ruby
|
23
|
-
|
24
|
-
DEPENDENCIES
|
25
|
-
bump
|
26
|
-
rake
|
27
|
-
rspec (~> 2)
|
28
|
-
zombie_passenger_killer!
|
data/Rakefile
DELETED
data/spec/spec_helper.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require 'zombie_passenger_killer'
|
@@ -1,186 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ZombiePassengerKiller do
|
4
|
-
let(:killer){
|
5
|
-
ZombiePassengerKiller::Reaper.new(@options || {}).tap do |k|
|
6
|
-
k.stub!(:passenger_pids).and_return([111])
|
7
|
-
k.out = StringIO.new
|
8
|
-
end
|
9
|
-
}
|
10
|
-
|
11
|
-
def output
|
12
|
-
killer.out.rewind
|
13
|
-
killer.out.read
|
14
|
-
end
|
15
|
-
|
16
|
-
it "has a VERSION" do
|
17
|
-
ZombiePassengerKiller::VERSION.should =~ /^\d+\.\d+\.\d+$/
|
18
|
-
end
|
19
|
-
|
20
|
-
describe "#hunt_zombies" do
|
21
|
-
it "does not kill anything by default" do
|
22
|
-
killer.should_not_receive(:kill_zombie)
|
23
|
-
killer.hunt_zombies
|
24
|
-
end
|
25
|
-
|
26
|
-
it "finds the right zombies" do
|
27
|
-
killer.stub!(:passenger_pids).and_return([123])
|
28
|
-
killer.stub!(:process_status).and_return([{:pid => 124, :cpu => 0}])
|
29
|
-
killer.should_receive(:kill_zombie).with(124)
|
30
|
-
killer.hunt_zombies
|
31
|
-
end
|
32
|
-
|
33
|
-
it "does not blow up when there are more processes in pids then status" do
|
34
|
-
@options = {:max => 1}
|
35
|
-
killer.stub!(:passenger_pids).and_return([123])
|
36
|
-
killer.stub!(:process_status).and_return([{:pid => 124, :cpu => 0}])
|
37
|
-
killer.should_receive(:kill_zombie).with(124)
|
38
|
-
killer.hunt_zombies
|
39
|
-
end
|
40
|
-
|
41
|
-
it "kills zombies with high cpu over max" do
|
42
|
-
@options = {:max => 1}
|
43
|
-
killer.stub!(:process_status).and_return([{:pid => 111, :cpu => 100}])
|
44
|
-
killer.should_receive(:kill_zombie).with(111)
|
45
|
-
killer.hunt_zombies
|
46
|
-
end
|
47
|
-
|
48
|
-
it "does not kills zombies with high cpu under max" do
|
49
|
-
@options = {:max => 2}
|
50
|
-
killer.stub!(:process_status).and_return([{:pid => 111, :cpu => 100}])
|
51
|
-
killer.should_not_receive(:kill_zombie).with(111)
|
52
|
-
killer.hunt_zombies
|
53
|
-
end
|
54
|
-
|
55
|
-
it "ignores high cpu levels in old history" do
|
56
|
-
@options = {:max => 2, :history => 2}
|
57
|
-
killer.should_not_receive(:kill_zombie).with(111)
|
58
|
-
killer.stub!(:process_status).and_return([{:pid => 111, :cpu => 100}])
|
59
|
-
killer.hunt_zombies
|
60
|
-
killer.stub!(:process_status).and_return([{:pid => 111, :cpu => 0}])
|
61
|
-
killer.hunt_zombies
|
62
|
-
killer.stub!(:process_status).and_return([{:pid => 111, :cpu => 100}])
|
63
|
-
killer.hunt_zombies
|
64
|
-
end
|
65
|
-
|
66
|
-
it "kills on high cpu levels in recent history" do
|
67
|
-
@options = {:max => 2, :history => 2}
|
68
|
-
killer.stub!(:process_status).and_return([{:pid => 111, :cpu => 100}])
|
69
|
-
killer.hunt_zombies
|
70
|
-
killer.should_receive(:kill_zombie).with(111)
|
71
|
-
killer.hunt_zombies
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
describe "#kill_zombies" do
|
76
|
-
before do
|
77
|
-
killer.instance_eval{
|
78
|
-
@grace_time = 0.1
|
79
|
-
@strace_time = 0.1
|
80
|
-
}
|
81
|
-
end
|
82
|
-
|
83
|
-
def pid_of(marker)
|
84
|
-
processes = `ps -ef | grep '#{marker}' | grep -v grep`
|
85
|
-
processes.strip.split("\n").last.split(/\s+/)[1].to_i
|
86
|
-
end
|
87
|
-
|
88
|
-
def start_bogus_process(options={})
|
89
|
-
marker = "TEST---#{rand(999999999999)}"
|
90
|
-
Thread.new do
|
91
|
-
`ruby -e 'at_exit{ puts "proper exit"; #{'sleep 10' if options[:hang]}}; sleep 10; puts "#{marker}"' 2>&1`
|
92
|
-
end
|
93
|
-
sleep 1 # give process time to spin up
|
94
|
-
pid_of(marker)
|
95
|
-
end
|
96
|
-
|
97
|
-
def process_alive?(pid)
|
98
|
-
Process.getpgid(pid)
|
99
|
-
rescue Errno::ESRCH
|
100
|
-
false
|
101
|
-
end
|
102
|
-
|
103
|
-
it "kills normal processes" do
|
104
|
-
pid = start_bogus_process
|
105
|
-
lambda{
|
106
|
-
killer.send(:kill_zombie, pid)
|
107
|
-
sleep 0.1
|
108
|
-
}.should change{ process_alive?(pid) }
|
109
|
-
end
|
110
|
-
|
111
|
-
it "kills hanging processes" do
|
112
|
-
pid = start_bogus_process :hang => true
|
113
|
-
lambda{
|
114
|
-
killer.send(:kill_zombie, pid)
|
115
|
-
sleep 0.1
|
116
|
-
}.should change{ process_alive?(pid) }
|
117
|
-
end
|
118
|
-
|
119
|
-
it "prints an strace of the process" do
|
120
|
-
pid = start_bogus_process
|
121
|
-
killer.send(:kill_zombie, pid)
|
122
|
-
output.should include('attach:')
|
123
|
-
end
|
124
|
-
|
125
|
-
it "does not take a strace of a dead process" do
|
126
|
-
killer.send(:kill_zombie, 111)
|
127
|
-
output.should_not include('attach:')
|
128
|
-
end
|
129
|
-
|
130
|
-
it "does not fail with an unknown pid" do
|
131
|
-
killer.send(:kill_zombie, 111)
|
132
|
-
output.should include('No such process')
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
describe "#log" do
|
137
|
-
it "logs simple when :show_times is not given" do
|
138
|
-
killer.send(:log, "X")
|
139
|
-
output.should == "X\n"
|
140
|
-
end
|
141
|
-
|
142
|
-
it "logs simple when :show_times is not given" do
|
143
|
-
@options = {:show_times => true}
|
144
|
-
killer.send(:log, "X")
|
145
|
-
output.should include(Time.now.year.to_s)
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
describe "#lurk" do
|
150
|
-
it "sleeps after checking" do
|
151
|
-
killer.should_receive(:hunt_zombies)
|
152
|
-
killer.should_receive(:sleep).with(10).and_raise "LOOP-BREAKER"
|
153
|
-
lambda{
|
154
|
-
killer.lurk
|
155
|
-
}.should raise_error "LOOP-BREAKER"
|
156
|
-
end
|
157
|
-
|
158
|
-
it "calls sleep with the given interval" do
|
159
|
-
@options = {:interval => 5}
|
160
|
-
killer.stub(:hunt_zombies)
|
161
|
-
killer.should_receive(:sleep).with(5).and_raise "LOOP-BREAKER"
|
162
|
-
lambda{
|
163
|
-
killer.lurk
|
164
|
-
}.should raise_error "LOOP-BREAKER"
|
165
|
-
end
|
166
|
-
|
167
|
-
it "prints Exiting on Interrupt" do
|
168
|
-
killer.stub(:hunt_zombies)
|
169
|
-
killer.should_receive(:sleep).and_raise Interrupt.new
|
170
|
-
lambda{
|
171
|
-
killer.lurk
|
172
|
-
}.should raise_error Interrupt
|
173
|
-
output.should include("Exiting")
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
describe "cli" do
|
178
|
-
it "prints its version" do
|
179
|
-
`./bin/zombie_passenger_killer -v`.should =~ /^\d+\.\d+\.\d+$/m
|
180
|
-
end
|
181
|
-
|
182
|
-
it "prints help" do
|
183
|
-
`./bin/zombie_passenger_killer -h`.should include('Usage')
|
184
|
-
end
|
185
|
-
end
|
186
|
-
end
|
@@ -1,12 +0,0 @@
|
|
1
|
-
$LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
|
2
|
-
require 'zombie_passenger_killer/version'
|
3
|
-
|
4
|
-
Gem::Specification.new "zombie_passenger_killer", ZombiePassengerKiller::VERSION do |s|
|
5
|
-
s.summary = "Guaranteed zombie passengers death"
|
6
|
-
s.authors = ["Michael Grosser"]
|
7
|
-
s.email = "michael@grosser.it"
|
8
|
-
s.homepage = "http://github.com/grosser/zombie_passenger_killer"
|
9
|
-
s.files = `git ls-files`.split("\n")
|
10
|
-
s.executables = ["zombie_passenger_killer"]
|
11
|
-
s.license = "MIT"
|
12
|
-
end
|