bluepill 0.0.66 → 0.0.67
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +1 -1
- data/.travis.yml +17 -0
- data/CONTRIBUTING.md +6 -0
- data/DESIGN.md +1 -1
- data/Gemfile +16 -4
- data/README.md +48 -15
- data/Rakefile +2 -2
- data/bin/bluepill +2 -2
- data/bin/bpsv +1 -1
- data/bin/sample_forking_server +5 -5
- data/bluepill.gemspec +6 -9
- data/lib/bluepill/application.rb +1 -1
- data/lib/bluepill/application/client.rb +1 -1
- data/lib/bluepill/application/server.rb +1 -1
- data/lib/bluepill/process_conditions/zombie_process.rb +19 -0
- data/lib/bluepill/system.rb +48 -33
- data/lib/bluepill/triggers/flapping.rb +1 -1
- data/lib/bluepill/version.rb +1 -1
- data/local-bluepill +2 -2
- data/spec/lib/bluepill/application_spec.rb +3 -3
- data/spec/lib/bluepill/logger_spec.rb +1 -1
- data/spec/lib/bluepill/process_spec.rb +19 -21
- data/spec/lib/bluepill/process_statistics_spec.rb +1 -1
- data/spec/lib/bluepill/system_spec.rb +2 -2
- data/spec/spec_helper.rb +5 -0
- metadata +45 -124
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: de6a6e9c8ca09b86c05408c467802998559911d1
|
4
|
+
data.tar.gz: 3a02ded7cad9e098e3add640a0da28310b794c0e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 828074cd01dbab698e803f9f73fdedfca8b808183f7a40d563b34ecde7541e63b6ebbbe73eb26d7b91b4d2f65a3f62afb0398e688f2d92df9ccf2add3e136541
|
7
|
+
data.tar.gz: 148bb1636929c5a7b4115c05a0c6296451e5d7db8a6a873fe3f602f9f761a0277942862d88f7dc0fcd849c06865f4d5b93f63fa6cf7996632a6b30e6452afbb2
|
data/.rspec
CHANGED
@@ -1 +1 @@
|
|
1
|
-
-r ./spec/spec_helper.rb -c -f progress
|
1
|
+
-r ./spec/spec_helper.rb -c -f progress
|
data/.travis.yml
ADDED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
Contributing
|
2
|
+
------------
|
3
|
+
|
4
|
+
To ease development and troubleshooting, a simple vagrant environment exists [here](https://github.com/iancoffey/chef_bluepill_devel). A "vagrant up" should do the trick.
|
5
|
+
|
6
|
+
As more OS options are added, this should also simplify the steps necessary to reproduce odd issues.
|
data/DESIGN.md
CHANGED
@@ -7,4 +7,4 @@ Here are just some bullet points of the design. We'll add details later.
|
|
7
7
|
* Use socket files to communicate between CLI and daemon
|
8
8
|
* DSL is a separate layer, the core of the monitoring just uses regular initializers, etc. DSL is simply for ease of use and should not interfere with business logic
|
9
9
|
* Sequentially process user issued commands so no weird race cases occur
|
10
|
-
* Triggers are notified by the state machine on any process state transitions
|
10
|
+
* Triggers are notified by the state machine on any process state transitions
|
data/Gemfile
CHANGED
@@ -3,8 +3,20 @@ source 'https://rubygems.org'
|
|
3
3
|
# Specify your gem's dependencies in bluepill.gemspec
|
4
4
|
gemspec
|
5
5
|
|
6
|
-
|
7
|
-
gem
|
6
|
+
gem 'activesupport', '~> 3.0', :platforms => [:ruby_18, :jruby]
|
7
|
+
gem 'rake'
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
group :doc do
|
10
|
+
# YARD helper for ruby 1.8 (already embedded into ruby 1.9)
|
11
|
+
gem 'ripper', :platforms => :mri_18
|
12
|
+
gem 'maruku', '>= 0.7'
|
13
|
+
gem 'yard', '>= 0.8'
|
14
|
+
end
|
15
|
+
|
16
|
+
group :test do
|
17
|
+
gem 'faker', '>= 1.2'
|
18
|
+
gem 'rspec', '>= 2.14'
|
19
|
+
gem 'simplecov', '>= 0.4', :platforms => :ruby_19
|
20
|
+
end
|
21
|
+
|
22
|
+
gem 'coveralls', :require => false, :platforms => [:mri_19, :mri_20], :group => :development
|
data/README.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
# Bluepill
|
2
|
-
Bluepill is a simple process monitoring tool written in Ruby.
|
2
|
+
Bluepill is a simple process monitoring tool written in Ruby.
|
3
|
+
|
4
|
+
[![Build Status](https://travis-ci.org/bluepill-rb/bluepill.png)](https://travis-ci.org/bluepill-rb/bluepill)
|
5
|
+
[![Dependency Status](https://gemnasium.com/bluepill-rb/bluepill.png)](https://gemnasium.com/bluepill-rb/bluepill)
|
6
|
+
[![Code Climate](https://codeclimate.com/github/bluepill-rb/bluepill.png)](https://codeclimate.com/github/bluepill-rb/bluepill)
|
7
|
+
[![Coverage Status](https://coveralls.io/repos/bluepill-rb/bluepill/badge.png)](https://coveralls.io/r/bluepill-rb/bluepill)
|
3
8
|
|
4
9
|
## Installation
|
5
10
|
It's hosted on [rubygems.org][rubygems].
|
@@ -50,7 +55,7 @@ Now if we want to do something more meaningful, like actually monitor the proces
|
|
50
55
|
app.process("process_name") do |process|
|
51
56
|
process.start_command = "/usr/bin/some_start_command"
|
52
57
|
process.pid_file = "/tmp/some_pid_file.pid"
|
53
|
-
|
58
|
+
|
54
59
|
process.checks :cpu_usage, :every => 10.seconds, :below => 5, :times => 3
|
55
60
|
end
|
56
61
|
end
|
@@ -66,7 +71,7 @@ To watch memory usage, we just add one more line:
|
|
66
71
|
process.start_command = "/usr/bin/some_start_command"
|
67
72
|
process.pid_file = "/tmp/some_pid_file.pid"
|
68
73
|
|
69
|
-
process.checks :cpu_usage, :every => 10.seconds, :below => 5, :times => 3
|
74
|
+
process.checks :cpu_usage, :every => 10.seconds, :below => 5, :times => 3
|
70
75
|
process.checks :mem_usage, :every => 10.seconds, :below => 100.megabytes, :times => [3,5]
|
71
76
|
end
|
72
77
|
end
|
@@ -80,7 +85,7 @@ To watch the modification time of a file, e.g. a log file to ensure the process
|
|
80
85
|
process.start_command = "/usr/bin/some_start_command"
|
81
86
|
process.pid_file = "/tmp/some_pid_file.pid"
|
82
87
|
|
83
|
-
process.checks :cpu_usage, :every => 10.seconds, :below => 5, :times => 3
|
88
|
+
process.checks :cpu_usage, :every => 10.seconds, :below => 5, :times => 3
|
84
89
|
process.checks :mem_usage, :every => 10.seconds, :below => 100.megabytes, :times => [3,5]
|
85
90
|
process.checks :file_time, :every => 60.seconds, :below => 3.minutes, :filename => "/tmp/some_file.log", :times => 2
|
86
91
|
end
|
@@ -113,7 +118,7 @@ We can tell bluepill to give a process some grace time to start/stop/restart bef
|
|
113
118
|
process.stop_grace_time = 5.seconds
|
114
119
|
process.restart_grace_time = 8.seconds
|
115
120
|
|
116
|
-
process.checks :cpu_usage, :every => 10.seconds, :below => 5, :times => 3
|
121
|
+
process.checks :cpu_usage, :every => 10.seconds, :below => 5, :times => 3
|
117
122
|
process.checks :mem_usage, :every => 10.seconds, :below => 100.megabytes, :times => [3,5]
|
118
123
|
end
|
119
124
|
end
|
@@ -143,7 +148,7 @@ If you want to run the process as someone other than root:
|
|
143
148
|
process.uid = "deploy"
|
144
149
|
process.gid = "deploy"
|
145
150
|
|
146
|
-
process.checks :cpu_usage, :every => 10.seconds, :below => 5, :times => 3
|
151
|
+
process.checks :cpu_usage, :every => 10.seconds, :below => 5, :times => 3
|
147
152
|
process.checks :mem_usage, :every => 10.seconds, :below => 100.megabytes, :times => [3,5]
|
148
153
|
end
|
149
154
|
end
|
@@ -257,7 +262,7 @@ And lastly, to monitor child processes:
|
|
257
262
|
process.monitor_children do |child_process|
|
258
263
|
child_process.checks :cpu_usage, :every => 10, :below => 5, :times => 3
|
259
264
|
child_process.checks :mem_usage, :every => 10, :below => 100.megabytes, :times => [3, 5]
|
260
|
-
|
265
|
+
|
261
266
|
child_process.stop_command = "kill -QUIT {{PID}}"
|
262
267
|
end
|
263
268
|
```
|
@@ -283,10 +288,10 @@ We recommend that you _not_ do that and instead use the config options to captur
|
|
283
288
|
Bluepill.application("app_name") do |app|
|
284
289
|
app.process("process_name") do |process|
|
285
290
|
process.start_command = "/usr/bin/env SOME_VAR=1 /usr/bin/some_start_command"
|
286
|
-
|
291
|
+
|
287
292
|
process.working_dir = "/tmp/some_dir"
|
288
293
|
process.stdout = process.stderr = "/tmp/server.log"
|
289
|
-
|
294
|
+
|
290
295
|
process.pid_file = "/tmp/some_pid_file.pid"
|
291
296
|
end
|
292
297
|
end
|
@@ -299,7 +304,7 @@ The main benefit of using the config options is that Bluepill will be able to mo
|
|
299
304
|
#### Usage
|
300
305
|
|
301
306
|
bluepill [app_name] command [options]
|
302
|
-
|
307
|
+
|
303
308
|
For the "load" command, the _app_name_ is specified in the config file, and
|
304
309
|
must not be provided on the command line.
|
305
310
|
|
@@ -331,7 +336,7 @@ To quit the bluepill daemon for an application:
|
|
331
336
|
|
332
337
|
sudo bluepill quit
|
333
338
|
|
334
|
-
### Logging
|
339
|
+
### Logging
|
335
340
|
By default, bluepill uses syslog local6 facility as described in the installation section. But if for any reason you don't want to use syslog, you can use a log file. You can do this by setting the :log\_file option in the config:
|
336
341
|
|
337
342
|
```ruby
|
@@ -341,7 +346,7 @@ By default, bluepill uses syslog local6 facility as described in the installatio
|
|
341
346
|
```
|
342
347
|
|
343
348
|
Keep in mind that you still need to set up log rotation (described in the installation section) to keep the log file from growing huge.
|
344
|
-
|
349
|
+
|
345
350
|
### Extra options
|
346
351
|
You can run bluepill in the foreground:
|
347
352
|
|
@@ -354,9 +359,37 @@ You can run bluepill in the foreground:
|
|
354
359
|
Note that You must define only one application per config when using foreground mode.
|
355
360
|
|
356
361
|
## Links
|
357
|
-
Code: [http://github.com/arya/bluepill](http://github.com/arya/bluepill)
|
358
|
-
Bugs/Features: [http://github.com/arya/bluepill/issues](http://github.com/arya/bluepill/issues)
|
359
|
-
Mailing List: [http://groups.google.com/group/bluepill-rb](http://groups.google.com/group/bluepill-rb)
|
360
362
|
|
363
|
+
* Code: [http://github.com/bluepill-rb/bluepill](http://github.com/bluepill-rb/bluepill)
|
364
|
+
* Bugs/Features: [http://github.com/bluepill-rb/bluepill/issues](http://github.com/bluepill-rb/bluepill/issues)
|
365
|
+
* Mailing List: [http://groups.google.com/group/bluepill-rb](http://groups.google.com/group/bluepill-rb)
|
361
366
|
|
362
367
|
[rubygems]: http://rubygems.org/gems/bluepill
|
368
|
+
|
369
|
+
## Supported Ruby Versions
|
370
|
+
This library aims to support and is [tested against][travis] the following Ruby
|
371
|
+
implementations:
|
372
|
+
|
373
|
+
* Ruby 1.8.7
|
374
|
+
* Ruby 1.9.2
|
375
|
+
* Ruby 1.9.3
|
376
|
+
* Ruby 2.0.0
|
377
|
+
* Ruby 2.1.0
|
378
|
+
* [JRuby][]
|
379
|
+
* [Rubinius][]
|
380
|
+
|
381
|
+
[jruby]: http://jruby.org/
|
382
|
+
[rubinius]: http://rubini.us/
|
383
|
+
|
384
|
+
If something doesn't work on one of these interpreters, please open an issue.
|
385
|
+
|
386
|
+
This library may inadvertently work (or seem to work) on other Ruby
|
387
|
+
implementations, however support will only be provided for the versions listed
|
388
|
+
above.
|
389
|
+
|
390
|
+
If you would like this library to support another Ruby version, you may
|
391
|
+
volunteer to be a maintainer. Being a maintainer entails making sure all tests
|
392
|
+
run and pass on that implementation. When something breaks on your
|
393
|
+
implementation, you will be responsible for providing patches in a timely
|
394
|
+
fashion. If critical issues for a particular implementation exist at the time
|
395
|
+
of a major release, support for that Ruby version may be dropped.
|
data/Rakefile
CHANGED
data/bin/bluepill
CHANGED
@@ -58,7 +58,7 @@ OptionParser.new do |opts|
|
|
58
58
|
puts " log [TARGET]\t\tShow the log for the specified process or group, defaults to all for app"
|
59
59
|
puts " quit\t\t\tStop bluepill"
|
60
60
|
puts
|
61
|
-
puts "See http://github.com/
|
61
|
+
puts "See http://github.com/bluepill-rb/bluepill#readme"
|
62
62
|
exit
|
63
63
|
end
|
64
64
|
|
@@ -114,7 +114,7 @@ if options[:command] == "load"
|
|
114
114
|
ENV['BLUEPILL_BASE_DIR'] = options[:base_dir]
|
115
115
|
|
116
116
|
exec(ruby, "-I#{load_path}", '-rbluepill', file_path)
|
117
|
-
|
117
|
+
|
118
118
|
else
|
119
119
|
$stderr.puts "Can't find file: #{file}"
|
120
120
|
end
|
data/bin/bpsv
CHANGED
data/bin/sample_forking_server
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
#! /usr/bin/env ruby
|
2
2
|
|
3
3
|
# This is a modified version found at http://tomayko.com/writings/unicorn-is-unix
|
4
|
-
# It is modified to trigger various states like increase memory consumption so that
|
4
|
+
# It is modified to trigger various states like increase memory consumption so that
|
5
5
|
# I could write watches for them.
|
6
6
|
|
7
7
|
# Instructions for running the test
|
8
|
-
#
|
8
|
+
#
|
9
9
|
# (1) Edit the example config and fix the path to this file. Around line 16.
|
10
10
|
# (2) Load up the config and run the bluepill daemon
|
11
11
|
# (3) Run watch -n0.2 'sudo ruby bin/bluepill status 2>/dev/null; echo; ps ajxu | egrep "(CPU|forking|bluepill|sleep|ruby)" | grep -v grep | sort'
|
@@ -30,7 +30,7 @@ trap('EXIT') { acceptor.close; children.each {|c| Process.kill('QUIT', c)} }
|
|
30
30
|
children << fork do
|
31
31
|
trap('QUIT') {$0 = "forking_server| QUIT received shutting down gracefully..."; sleep 5; exit}
|
32
32
|
trap('INT') {$0 = "forking_server| INT received shutting down UN-gracefully..."; sleep 3; exit}
|
33
|
-
|
33
|
+
|
34
34
|
puts "child #$$ accepting on shared socket (localhost:#{port})"
|
35
35
|
loop {
|
36
36
|
socket, addr = acceptor.accept
|
@@ -40,7 +40,7 @@ trap('EXIT') { acceptor.close; children.each {|c| Process.kill('QUIT', c)} }
|
|
40
40
|
socket.write message
|
41
41
|
socket.close
|
42
42
|
puts "child #$$ echo'd: '#{message.strip}'"
|
43
|
-
|
43
|
+
|
44
44
|
# cause a spike in mem usage
|
45
45
|
temp = "*" * (100 * 1024)
|
46
46
|
}
|
@@ -50,4 +50,4 @@ end
|
|
50
50
|
|
51
51
|
trap('INT') { puts "\nbailing" ; exit }
|
52
52
|
|
53
|
-
Process.waitall
|
53
|
+
Process.waitall
|
data/bluepill.gemspec
CHANGED
@@ -10,20 +10,17 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.platform = Gem::Platform::RUBY
|
11
11
|
s.authors = ["Arya Asemanfar", "Gary Tsang", "Rohith Ravi"]
|
12
12
|
s.email = ["entombedvirus@gmail.com"]
|
13
|
-
s.homepage = "http://github.com/
|
13
|
+
s.homepage = "http://github.com/bluepill-rb/bluepill"
|
14
14
|
s.summary = %q{A process monitor written in Ruby with stability and minimalism in mind.}
|
15
15
|
s.description = %q{Bluepill keeps your daemons up while taking up as little resources as possible. After all you probably want the resources of your server to be used by whatever daemons you are running rather than the thing that's supposed to make sure they are brought back up, should they die or misbehave.}
|
16
|
+
s.license = 'MIT'
|
16
17
|
|
17
|
-
s.add_dependency '
|
18
|
+
s.add_dependency 'activesupport', ['>= 3', '< 4.1']
|
19
|
+
s.add_dependency 'blue-daemons', '~> 1.1.11'
|
20
|
+
s.add_dependency 'i18n', '~> 0.5'
|
18
21
|
s.add_dependency 'state_machine', '~> 1.1'
|
19
|
-
s.add_dependency 'activesupport', '>= 3.0.0', '< 4.0.0'
|
20
|
-
s.add_dependency 'i18n', '>= 0.5.0'
|
21
22
|
|
22
|
-
s.add_development_dependency 'bundler', '
|
23
|
-
s.add_development_dependency 'rake', '!= 0.9.0'
|
24
|
-
s.add_development_dependency 'rspec', '~> 2.12.0'
|
25
|
-
s.add_development_dependency 'faker', '~> 0.9'
|
26
|
-
s.add_development_dependency 'yard', '~> 0.7'
|
23
|
+
s.add_development_dependency 'bundler', '~> 1.3'
|
27
24
|
|
28
25
|
s.files = `git ls-files`.split("\n")
|
29
26
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
data/lib/bluepill/application.rb
CHANGED
@@ -16,7 +16,7 @@ module Bluepill
|
|
16
16
|
|
17
17
|
@foreground = options[:foreground]
|
18
18
|
self.log_file = options[:log_file]
|
19
|
-
self.base_dir = ProcessJournal.base_dir = options[:base_dir] ||
|
19
|
+
self.base_dir = ProcessJournal.base_dir = options[:base_dir] ||
|
20
20
|
ENV['BLUEPILL_BASE_DIR'] ||
|
21
21
|
(::Process.euid != 0 ? File.join(ENV['HOME'], '.bluepill') : "/var/run/bluepill")
|
22
22
|
self.pid_file = File.join(self.base_dir, 'pids', self.name + ".pid")
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
module Bluepill
|
3
|
+
module ProcessConditions
|
4
|
+
# Process must have cache_actual_pid set to false to function correctly:
|
5
|
+
#
|
6
|
+
# process.checks :zombie_process, :every => 5.seconds
|
7
|
+
# process.cache_actual_pid = false
|
8
|
+
|
9
|
+
class ZombieProcess < ProcessCondition
|
10
|
+
def run(pid, include_children)
|
11
|
+
System.command(pid)
|
12
|
+
end
|
13
|
+
|
14
|
+
def check(value)
|
15
|
+
(value =~ /\<defunct\>/).nil?
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/bluepill/system.rb
CHANGED
@@ -15,7 +15,8 @@ module Bluepill
|
|
15
15
|
:ppid => 1,
|
16
16
|
:pcpu => 2,
|
17
17
|
:rss => 3,
|
18
|
-
:etime => 4
|
18
|
+
:etime => 4,
|
19
|
+
:command => 5
|
19
20
|
}
|
20
21
|
|
21
22
|
def pid_alive?(pid)
|
@@ -36,7 +37,7 @@ module Bluepill
|
|
36
37
|
get_children(pid).each { |child_pid|
|
37
38
|
cpu_used += ps[child_pid][IDX_MAP[:pcpu]].to_f if ps[child_pid]
|
38
39
|
} if include_children
|
39
|
-
cpu_used
|
40
|
+
cpu_used
|
40
41
|
end
|
41
42
|
|
42
43
|
def memory_usage(pid, include_children)
|
@@ -55,13 +56,19 @@ module Bluepill
|
|
55
56
|
parse_elapsed_time(ps[pid][IDX_MAP[:etime]])
|
56
57
|
end
|
57
58
|
|
59
|
+
def command(pid)
|
60
|
+
ps = ps_axu
|
61
|
+
return unless ps[pid]
|
62
|
+
ps[pid][IDX_MAP[:command]]
|
63
|
+
end
|
64
|
+
|
58
65
|
def get_children(parent_pid)
|
59
66
|
child_pids = Array.new
|
60
67
|
ps_axu.each_pair do |pid, chunks|
|
61
68
|
child_pids << chunks[IDX_MAP[:pid]].to_i if chunks[IDX_MAP[:ppid]].to_i == parent_pid.to_i
|
62
69
|
end
|
63
70
|
grand_children = child_pids.map{|pid| get_children(pid)}.flatten
|
64
|
-
child_pids.concat grand_children
|
71
|
+
child_pids.concat grand_children
|
65
72
|
end
|
66
73
|
|
67
74
|
# Returns the pid of the child that executes the cmd
|
@@ -107,7 +114,7 @@ module Bluepill
|
|
107
114
|
wr.write daemon_id
|
108
115
|
wr.close
|
109
116
|
|
110
|
-
exit
|
117
|
+
::Process::exit!(true)
|
111
118
|
end
|
112
119
|
end
|
113
120
|
|
@@ -118,7 +125,7 @@ module Bluepill
|
|
118
125
|
File.unlink(filename) if filename && File.exists?(filename)
|
119
126
|
rescue IOError, Errno::ENOENT
|
120
127
|
rescue Errno::EACCES
|
121
|
-
retry if (tries += 1) < 3
|
128
|
+
retry if (tries += 1) < 3
|
122
129
|
$stderr.puts("Warning: permission denied trying to delete #{filename}")
|
123
130
|
end
|
124
131
|
end
|
@@ -146,32 +153,38 @@ module Bluepill
|
|
146
153
|
cmd_err_read, cmd_err_write = IO.pipe
|
147
154
|
|
148
155
|
pid = fork {
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
156
|
+
begin
|
157
|
+
# grandchild
|
158
|
+
drop_privileges(options[:uid], options[:gid], options[:supplementary_groups])
|
159
|
+
|
160
|
+
Dir.chdir(ENV["PWD"] = options[:working_dir].to_s) if options[:working_dir]
|
161
|
+
options[:environment].each { |key, value| ENV[key.to_s] = value.to_s } if options[:environment]
|
162
|
+
|
163
|
+
# close unused fds so ancestors wont hang. This line is the only reason we are not
|
164
|
+
# using something like popen3. If this fd is not closed, the .read call on the parent
|
165
|
+
# will never return because "wr" would still be open in the "exec"-ed cmd
|
166
|
+
wr.close
|
167
|
+
|
168
|
+
# we do not care about stdin of cmd
|
169
|
+
STDIN.reopen("/dev/null")
|
170
|
+
|
171
|
+
# point stdout of cmd to somewhere we can read
|
172
|
+
cmd_out_read.close
|
173
|
+
STDOUT.reopen(cmd_out_write)
|
174
|
+
cmd_out_write.close
|
175
|
+
|
176
|
+
# same thing for stderr
|
177
|
+
cmd_err_read.close
|
178
|
+
STDERR.reopen(cmd_err_write)
|
179
|
+
cmd_err_write.close
|
180
|
+
|
181
|
+
# finally, replace grandchild with cmd
|
182
|
+
::Kernel.exec(*Shellwords.shellwords(cmd))
|
183
|
+
rescue Exception => e
|
184
|
+
(cmd_err_write.closed? ? STDERR : cmd_err_write).puts "Exception in grandchild: #{e.to_s}."
|
185
|
+
(cmd_err_write.closed? ? STDERR : cmd_err_write).puts e.backtrace
|
186
|
+
exit 1
|
187
|
+
end
|
175
188
|
}
|
176
189
|
|
177
190
|
# we do not use these ends of the pipes in the child
|
@@ -212,13 +225,15 @@ module Bluepill
|
|
212
225
|
# TODO: need a mutex here
|
213
226
|
store[:ps_axu] ||= begin
|
214
227
|
# BSD style ps invocation
|
215
|
-
lines = `ps axo pid,ppid,pcpu,rss,etime`.split("\n")
|
228
|
+
lines = `ps axo pid,ppid,pcpu,rss,etime,command`.split("\n")
|
216
229
|
|
217
230
|
lines.inject(Hash.new) do |mem, line|
|
218
231
|
chunks = line.split(/\s+/)
|
219
232
|
chunks.delete_if {|c| c.strip.empty? }
|
220
233
|
pid = chunks[IDX_MAP[:pid]].strip.to_i
|
221
|
-
|
234
|
+
command = chunks.slice!(IDX_MAP[:command], chunks.length).join ' '
|
235
|
+
chunks[IDX_MAP[:command]] = command
|
236
|
+
mem[pid] = chunks.flatten
|
222
237
|
mem
|
223
238
|
end
|
224
239
|
end
|
@@ -35,7 +35,7 @@ module Bluepill
|
|
35
35
|
def check_flapping
|
36
36
|
# The process has not flapped if we haven't encountered enough incidents
|
37
37
|
return unless (@timeline.compact.length == self.times)
|
38
|
-
|
38
|
+
|
39
39
|
# Check if the incident happend within the timeframe
|
40
40
|
duration = (@timeline.last - @timeline.first) <= self.within
|
41
41
|
|
data/lib/bluepill/version.rb
CHANGED
data/local-bluepill
CHANGED
@@ -63,7 +63,7 @@ OptionParser.new do |opts|
|
|
63
63
|
puts " log [TARGET]\t\tShow the log for the specified process or group, defaults to all for app"
|
64
64
|
puts " quit\t\t\tStop bluepill"
|
65
65
|
puts
|
66
|
-
puts "See http://github.com/
|
66
|
+
puts "See http://github.com/bluepill-rb/bluepill#readme"
|
67
67
|
exit
|
68
68
|
end
|
69
69
|
|
@@ -119,7 +119,7 @@ if options[:command] == "load"
|
|
119
119
|
ENV['BLUEPILL_BASE_DIR'] = options[:base_dir]
|
120
120
|
|
121
121
|
exec(ruby, "-I#{load_path}", '-rbluepill', file_path)
|
122
|
-
|
122
|
+
|
123
123
|
else
|
124
124
|
$stderr.puts "Can't find file: #{file}"
|
125
125
|
end
|
@@ -3,7 +3,7 @@ describe Bluepill::Application do
|
|
3
3
|
let(:options){ {} }
|
4
4
|
subject {described_class.new('test', options)}
|
5
5
|
before(:each) {described_class.any_instance.should_receive(:setup_pids_dir)}
|
6
|
-
|
6
|
+
|
7
7
|
context "when euid is not root" do
|
8
8
|
before(:each) {::Process.stub(:euid).and_return(1)}
|
9
9
|
its(:base_dir){ should eq(File.join(ENV['HOME'], '.bluepill')) }
|
@@ -12,7 +12,7 @@ describe Bluepill::Application do
|
|
12
12
|
before(:each) {::Process.stub(:euid).and_return(0)}
|
13
13
|
its(:base_dir) { should eq('/var/run/bluepill') }
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
context "when option base_dir is specified" do
|
17
17
|
let(:options) { {:base_dir=>'/var/bluepill'} }
|
18
18
|
its(:base_dir) { should eq(options[:base_dir]) }
|
@@ -28,4 +28,4 @@ describe Bluepill::Application do
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
end
|
31
|
-
end
|
31
|
+
end
|
@@ -5,9 +5,7 @@ describe Bluepill::Process do
|
|
5
5
|
end
|
6
6
|
|
7
7
|
subject do
|
8
|
-
Bluepill::Process.new(:proc_name, [],
|
9
|
-
:logger => Bluepill::Logger.new,
|
10
|
-
)
|
8
|
+
Bluepill::Process.new(:proc_name, [], :logger => Bluepill::Logger.new)
|
11
9
|
end
|
12
10
|
|
13
11
|
describe "#initialize" do
|
@@ -41,13 +39,13 @@ describe Bluepill::Process do
|
|
41
39
|
subject.logger.stub(:warning)
|
42
40
|
subject.stub(:daemonize?) { false }
|
43
41
|
|
44
|
-
subject.should_receive(:with_timeout)
|
45
|
-
|
46
|
-
|
42
|
+
subject.should_receive(:with_timeout).
|
43
|
+
with(3, "freakout").
|
44
|
+
and_yield
|
47
45
|
|
48
|
-
Bluepill::System.should_receive(:execute_blocking)
|
49
|
-
|
50
|
-
|
46
|
+
Bluepill::System.should_receive(:execute_blocking).
|
47
|
+
with("/etc/init.d/script start", subject.system_command_options).
|
48
|
+
and_return(:exit_code => 0)
|
51
49
|
|
52
50
|
subject.start_process
|
53
51
|
end
|
@@ -56,13 +54,13 @@ describe Bluepill::Process do
|
|
56
54
|
it "functions" do
|
57
55
|
subject.stub(:stop_command) { "/etc/init.d/script stop" }
|
58
56
|
subject.logger.stub(:warning)
|
59
|
-
subject.should_receive(:with_timeout)
|
60
|
-
|
61
|
-
|
57
|
+
subject.should_receive(:with_timeout).
|
58
|
+
with(3, "stop").
|
59
|
+
and_yield
|
62
60
|
|
63
|
-
Bluepill::System.should_receive(:execute_blocking)
|
64
|
-
|
65
|
-
|
61
|
+
Bluepill::System.should_receive(:execute_blocking).
|
62
|
+
with("/etc/init.d/script stop", subject.system_command_options).
|
63
|
+
and_return(:exit_code => 0)
|
66
64
|
|
67
65
|
subject.stop_process
|
68
66
|
end
|
@@ -72,13 +70,13 @@ describe Bluepill::Process do
|
|
72
70
|
it "functions" do
|
73
71
|
subject.stub(:restart_command) { "/etc/init.d/script restart" }
|
74
72
|
subject.logger.stub(:warning)
|
75
|
-
subject.should_receive(:with_timeout)
|
76
|
-
|
77
|
-
|
73
|
+
subject.should_receive(:with_timeout).
|
74
|
+
with(3, "restart").
|
75
|
+
and_yield
|
78
76
|
|
79
|
-
Bluepill::System.should_receive(:execute_blocking)
|
80
|
-
|
81
|
-
|
77
|
+
Bluepill::System.should_receive(:execute_blocking).
|
78
|
+
with("/etc/init.d/script restart", subject.system_command_options).
|
79
|
+
and_return(:exit_code => 0)
|
82
80
|
|
83
81
|
subject.restart_process
|
84
82
|
end
|
@@ -17,12 +17,12 @@ describe Bluepill::System do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
it "should return same Hash or every call" do
|
20
|
-
Bluepill::System.store.should be_equal(Bluepill::System.store)
|
20
|
+
Bluepill::System.store.should be_equal(Bluepill::System.store)
|
21
21
|
end
|
22
22
|
|
23
23
|
it "should store assigned pairs" do
|
24
24
|
Bluepill::System.store[:somekey] = 10
|
25
|
-
Bluepill::System.store[:somekey].should be_eql(10)
|
25
|
+
Bluepill::System.store[:somekey].should be_eql(10)
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bluepill
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.67
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Arya Asemanfar
|
@@ -11,158 +10,84 @@ authors:
|
|
11
10
|
autorequire:
|
12
11
|
bindir: bin
|
13
12
|
cert_chain: []
|
14
|
-
date:
|
13
|
+
date: 2014-05-01 00:00:00.000000000 Z
|
15
14
|
dependencies:
|
16
|
-
- !ruby/object:Gem::Dependency
|
17
|
-
name: daemons
|
18
|
-
requirement: !ruby/object:Gem::Requirement
|
19
|
-
none: false
|
20
|
-
requirements:
|
21
|
-
- - ~>
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: 1.1.4
|
24
|
-
type: :runtime
|
25
|
-
prerelease: false
|
26
|
-
version_requirements: !ruby/object:Gem::Requirement
|
27
|
-
none: false
|
28
|
-
requirements:
|
29
|
-
- - ~>
|
30
|
-
- !ruby/object:Gem::Version
|
31
|
-
version: 1.1.4
|
32
|
-
- !ruby/object:Gem::Dependency
|
33
|
-
name: state_machine
|
34
|
-
requirement: !ruby/object:Gem::Requirement
|
35
|
-
none: false
|
36
|
-
requirements:
|
37
|
-
- - ~>
|
38
|
-
- !ruby/object:Gem::Version
|
39
|
-
version: '1.1'
|
40
|
-
type: :runtime
|
41
|
-
prerelease: false
|
42
|
-
version_requirements: !ruby/object:Gem::Requirement
|
43
|
-
none: false
|
44
|
-
requirements:
|
45
|
-
- - ~>
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '1.1'
|
48
15
|
- !ruby/object:Gem::Dependency
|
49
16
|
name: activesupport
|
50
17
|
requirement: !ruby/object:Gem::Requirement
|
51
|
-
none: false
|
52
18
|
requirements:
|
53
|
-
- -
|
19
|
+
- - ">="
|
54
20
|
- !ruby/object:Gem::Version
|
55
|
-
version: 3
|
56
|
-
- - <
|
21
|
+
version: '3'
|
22
|
+
- - "<"
|
57
23
|
- !ruby/object:Gem::Version
|
58
|
-
version: 4.
|
24
|
+
version: '4.1'
|
59
25
|
type: :runtime
|
60
26
|
prerelease: false
|
61
27
|
version_requirements: !ruby/object:Gem::Requirement
|
62
|
-
none: false
|
63
28
|
requirements:
|
64
|
-
- -
|
29
|
+
- - ">="
|
65
30
|
- !ruby/object:Gem::Version
|
66
|
-
version: 3
|
67
|
-
- - <
|
31
|
+
version: '3'
|
32
|
+
- - "<"
|
68
33
|
- !ruby/object:Gem::Version
|
69
|
-
version: 4.
|
34
|
+
version: '4.1'
|
70
35
|
- !ruby/object:Gem::Dependency
|
71
|
-
name:
|
36
|
+
name: blue-daemons
|
72
37
|
requirement: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
38
|
requirements:
|
75
|
-
- -
|
39
|
+
- - "~>"
|
76
40
|
- !ruby/object:Gem::Version
|
77
|
-
version:
|
41
|
+
version: 1.1.11
|
78
42
|
type: :runtime
|
79
43
|
prerelease: false
|
80
44
|
version_requirements: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
|
-
requirements:
|
83
|
-
- - ! '>='
|
84
|
-
- !ruby/object:Gem::Version
|
85
|
-
version: 0.5.0
|
86
|
-
- !ruby/object:Gem::Dependency
|
87
|
-
name: bundler
|
88
|
-
requirement: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
|
-
requirements:
|
91
|
-
- - ! '>='
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
version: 1.0.10
|
94
|
-
type: :development
|
95
|
-
prerelease: false
|
96
|
-
version_requirements: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
45
|
requirements:
|
99
|
-
- -
|
46
|
+
- - "~>"
|
100
47
|
- !ruby/object:Gem::Version
|
101
|
-
version: 1.
|
48
|
+
version: 1.1.11
|
102
49
|
- !ruby/object:Gem::Dependency
|
103
|
-
name:
|
104
|
-
requirement: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
|
-
requirements:
|
107
|
-
- - ! '!='
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
version: 0.9.0
|
110
|
-
type: :development
|
111
|
-
prerelease: false
|
112
|
-
version_requirements: !ruby/object:Gem::Requirement
|
113
|
-
none: false
|
114
|
-
requirements:
|
115
|
-
- - ! '!='
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: 0.9.0
|
118
|
-
- !ruby/object:Gem::Dependency
|
119
|
-
name: rspec
|
50
|
+
name: i18n
|
120
51
|
requirement: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
52
|
requirements:
|
123
|
-
- - ~>
|
53
|
+
- - "~>"
|
124
54
|
- !ruby/object:Gem::Version
|
125
|
-
version:
|
126
|
-
type: :
|
55
|
+
version: '0.5'
|
56
|
+
type: :runtime
|
127
57
|
prerelease: false
|
128
58
|
version_requirements: !ruby/object:Gem::Requirement
|
129
|
-
none: false
|
130
59
|
requirements:
|
131
|
-
- - ~>
|
60
|
+
- - "~>"
|
132
61
|
- !ruby/object:Gem::Version
|
133
|
-
version:
|
62
|
+
version: '0.5'
|
134
63
|
- !ruby/object:Gem::Dependency
|
135
|
-
name:
|
64
|
+
name: state_machine
|
136
65
|
requirement: !ruby/object:Gem::Requirement
|
137
|
-
none: false
|
138
66
|
requirements:
|
139
|
-
- - ~>
|
67
|
+
- - "~>"
|
140
68
|
- !ruby/object:Gem::Version
|
141
|
-
version: '
|
142
|
-
type: :
|
69
|
+
version: '1.1'
|
70
|
+
type: :runtime
|
143
71
|
prerelease: false
|
144
72
|
version_requirements: !ruby/object:Gem::Requirement
|
145
|
-
none: false
|
146
73
|
requirements:
|
147
|
-
- - ~>
|
74
|
+
- - "~>"
|
148
75
|
- !ruby/object:Gem::Version
|
149
|
-
version: '
|
76
|
+
version: '1.1'
|
150
77
|
- !ruby/object:Gem::Dependency
|
151
|
-
name:
|
78
|
+
name: bundler
|
152
79
|
requirement: !ruby/object:Gem::Requirement
|
153
|
-
none: false
|
154
80
|
requirements:
|
155
|
-
- - ~>
|
81
|
+
- - "~>"
|
156
82
|
- !ruby/object:Gem::Version
|
157
|
-
version: '
|
83
|
+
version: '1.3'
|
158
84
|
type: :development
|
159
85
|
prerelease: false
|
160
86
|
version_requirements: !ruby/object:Gem::Requirement
|
161
|
-
none: false
|
162
87
|
requirements:
|
163
|
-
- - ~>
|
88
|
+
- - "~>"
|
164
89
|
- !ruby/object:Gem::Version
|
165
|
-
version: '
|
90
|
+
version: '1.3'
|
166
91
|
description: Bluepill keeps your daemons up while taking up as little resources as
|
167
92
|
possible. After all you probably want the resources of your server to be used by
|
168
93
|
whatever daemons you are running rather than the thing that's supposed to make sure
|
@@ -178,8 +103,10 @@ extra_rdoc_files:
|
|
178
103
|
- LICENSE
|
179
104
|
- README.md
|
180
105
|
files:
|
181
|
-
- .gitignore
|
182
|
-
- .rspec
|
106
|
+
- ".gitignore"
|
107
|
+
- ".rspec"
|
108
|
+
- ".travis.yml"
|
109
|
+
- CONTRIBUTING.md
|
183
110
|
- DESIGN.md
|
184
111
|
- Gemfile
|
185
112
|
- LICENSE
|
@@ -214,6 +141,7 @@ files:
|
|
214
141
|
- lib/bluepill/process_conditions/mem_usage.rb
|
215
142
|
- lib/bluepill/process_conditions/process_condition.rb
|
216
143
|
- lib/bluepill/process_conditions/running_time.rb
|
144
|
+
- lib/bluepill/process_conditions/zombie_process.rb
|
217
145
|
- lib/bluepill/process_journal.rb
|
218
146
|
- lib/bluepill/process_statistics.rb
|
219
147
|
- lib/bluepill/socket.rb
|
@@ -229,35 +157,29 @@ files:
|
|
229
157
|
- spec/lib/bluepill/process_statistics_spec.rb
|
230
158
|
- spec/lib/bluepill/system_spec.rb
|
231
159
|
- spec/spec_helper.rb
|
232
|
-
homepage: http://github.com/
|
233
|
-
licenses:
|
160
|
+
homepage: http://github.com/bluepill-rb/bluepill
|
161
|
+
licenses:
|
162
|
+
- MIT
|
163
|
+
metadata: {}
|
234
164
|
post_install_message:
|
235
165
|
rdoc_options: []
|
236
166
|
require_paths:
|
237
167
|
- lib
|
238
168
|
required_ruby_version: !ruby/object:Gem::Requirement
|
239
|
-
none: false
|
240
169
|
requirements:
|
241
|
-
- -
|
170
|
+
- - ">="
|
242
171
|
- !ruby/object:Gem::Version
|
243
172
|
version: '0'
|
244
|
-
segments:
|
245
|
-
- 0
|
246
|
-
hash: 697790739872167949
|
247
173
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
248
|
-
none: false
|
249
174
|
requirements:
|
250
|
-
- -
|
175
|
+
- - ">="
|
251
176
|
- !ruby/object:Gem::Version
|
252
177
|
version: '0'
|
253
|
-
segments:
|
254
|
-
- 0
|
255
|
-
hash: 697790739872167949
|
256
178
|
requirements: []
|
257
179
|
rubyforge_project:
|
258
|
-
rubygems_version:
|
180
|
+
rubygems_version: 2.2.2
|
259
181
|
signing_key:
|
260
|
-
specification_version:
|
182
|
+
specification_version: 4
|
261
183
|
summary: A process monitor written in Ruby with stability and minimalism in mind.
|
262
184
|
test_files:
|
263
185
|
- spec/lib/bluepill/application_spec.rb
|
@@ -266,4 +188,3 @@ test_files:
|
|
266
188
|
- spec/lib/bluepill/process_statistics_spec.rb
|
267
189
|
- spec/lib/bluepill/system_spec.rb
|
268
190
|
- spec/spec_helper.rb
|
269
|
-
has_rdoc:
|