bluepill 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/bin/bluepill +2 -2
- data/bluepill.gemspec +88 -0
- data/lib/bluepill/application.rb +17 -13
- data/lib/bluepill/condition_watch.rb +5 -4
- data/lib/bluepill/controller.rb +11 -0
- data/lib/bluepill/group.rb +1 -6
- data/lib/bluepill/logger.rb +19 -7
- data/lib/bluepill/process.rb +14 -9
- data/lib/example.rb +4 -4
- metadata +2 -1
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.2
|
data/bin/bluepill
CHANGED
@@ -5,7 +5,6 @@ require 'bluepill'
|
|
5
5
|
|
6
6
|
# defaults
|
7
7
|
options = {
|
8
|
-
:application => "all",
|
9
8
|
:log_file => "/var/log/bluepill.log"
|
10
9
|
}
|
11
10
|
|
@@ -37,6 +36,7 @@ case options[:command]
|
|
37
36
|
when "load"
|
38
37
|
file = ARGV.shift
|
39
38
|
eval(File.read(file))
|
39
|
+
|
40
40
|
when "log"
|
41
41
|
pattern = ARGV.shift
|
42
42
|
pattern = controller.send_cmd(options[:application], :grep_pattern, pattern)
|
@@ -49,5 +49,5 @@ when *ALLOWED_COMMANDS
|
|
49
49
|
puts controller.send_cmd(options[:application], options[:command], process_or_group_name)
|
50
50
|
|
51
51
|
else
|
52
|
-
"Unknown command `%s`" % options[:command]
|
52
|
+
puts "Unknown command `%s`" % options[:command]
|
53
53
|
end
|
data/bluepill.gemspec
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{bluepill}
|
8
|
+
s.version = "0.0.2"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Arya Asemanfar", "Gary Tsang", "Rohith Ravi"]
|
12
|
+
s.date = %q{2009-10-05}
|
13
|
+
s.default_executable = %q{bluepill}
|
14
|
+
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.}
|
15
|
+
s.email = %q{entombedvirus@gmail.com}
|
16
|
+
s.executables = ["bluepill"]
|
17
|
+
s.extra_rdoc_files = [
|
18
|
+
"LICENSE",
|
19
|
+
"README",
|
20
|
+
"README.rdoc"
|
21
|
+
]
|
22
|
+
s.files = [
|
23
|
+
".document",
|
24
|
+
".gitignore",
|
25
|
+
"LICENSE",
|
26
|
+
"README",
|
27
|
+
"README.rdoc",
|
28
|
+
"Rakefile",
|
29
|
+
"VERSION",
|
30
|
+
"bin/bluepill",
|
31
|
+
"bluepill.gemspec",
|
32
|
+
"lib/bluepill.rb",
|
33
|
+
"lib/bluepill/application.rb",
|
34
|
+
"lib/bluepill/application/client.rb",
|
35
|
+
"lib/bluepill/application/server.rb",
|
36
|
+
"lib/bluepill/comm.rb",
|
37
|
+
"lib/bluepill/condition_watch.rb",
|
38
|
+
"lib/bluepill/controller.rb",
|
39
|
+
"lib/bluepill/dsl.rb",
|
40
|
+
"lib/bluepill/group.rb",
|
41
|
+
"lib/bluepill/logger.rb",
|
42
|
+
"lib/bluepill/process.rb",
|
43
|
+
"lib/bluepill/process_conditions.rb",
|
44
|
+
"lib/bluepill/process_conditions/always_true.rb",
|
45
|
+
"lib/bluepill/process_conditions/cpu_usage.rb",
|
46
|
+
"lib/bluepill/process_conditions/mem_usage.rb",
|
47
|
+
"lib/bluepill/process_conditions/process_condition.rb",
|
48
|
+
"lib/bluepill/socket.rb",
|
49
|
+
"lib/bluepill/util/rotational_array.rb",
|
50
|
+
"lib/example.rb",
|
51
|
+
"spec/blue-pill_spec.rb",
|
52
|
+
"spec/process_spec.rb",
|
53
|
+
"spec/spec_helper.rb"
|
54
|
+
]
|
55
|
+
s.has_rdoc = true
|
56
|
+
s.homepage = %q{http://github.com/arya/bluepill}
|
57
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
58
|
+
s.require_paths = ["lib"]
|
59
|
+
s.rubygems_version = %q{1.3.2}
|
60
|
+
s.summary = %q{A process monitor written in Ruby with stability and minimalism in mind.}
|
61
|
+
s.test_files = [
|
62
|
+
"spec/blue-pill_spec.rb",
|
63
|
+
"spec/process_spec.rb",
|
64
|
+
"spec/spec_helper.rb"
|
65
|
+
]
|
66
|
+
|
67
|
+
if s.respond_to? :specification_version then
|
68
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
69
|
+
s.specification_version = 3
|
70
|
+
|
71
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
72
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
73
|
+
s.add_runtime_dependency(%q<daemons>, [">= 1.0.9"])
|
74
|
+
s.add_runtime_dependency(%q<pluginaweek-state_machine>, [">= 0.8.0"])
|
75
|
+
s.add_runtime_dependency(%q<activesupport>, [">= 2.0.2"])
|
76
|
+
else
|
77
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
78
|
+
s.add_dependency(%q<daemons>, [">= 1.0.9"])
|
79
|
+
s.add_dependency(%q<pluginaweek-state_machine>, [">= 0.8.0"])
|
80
|
+
s.add_dependency(%q<activesupport>, [">= 2.0.2"])
|
81
|
+
end
|
82
|
+
else
|
83
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
84
|
+
s.add_dependency(%q<daemons>, [">= 1.0.9"])
|
85
|
+
s.add_dependency(%q<pluginaweek-state_machine>, [">= 0.8.0"])
|
86
|
+
s.add_dependency(%q<activesupport>, [">= 2.0.2"])
|
87
|
+
end
|
88
|
+
end
|
data/lib/bluepill/application.rb
CHANGED
@@ -1,18 +1,14 @@
|
|
1
|
-
require 'logger'
|
2
|
-
|
3
1
|
module Bluepill
|
4
2
|
class Application
|
5
3
|
attr_accessor :name, :logger, :base_dir, :socket, :pid_file
|
6
|
-
attr_accessor :groups
|
4
|
+
attr_accessor :groups
|
7
5
|
|
8
6
|
def initialize(name, options = {})
|
9
7
|
self.name = name
|
10
8
|
self.base_dir = options[:base_dir] ||= '/var/bluepill'
|
11
9
|
|
12
|
-
self.logger = Bluepill::Logger.new
|
13
|
-
self.group_logger = Bluepill::Logger.new(self.logger, "#{self.name}:") if self.logger
|
10
|
+
self.logger = Bluepill::Logger.new.prefix_with(self.name)
|
14
11
|
|
15
|
-
# self.groups = Hash.new { |h,k| h[k] = Group.new(k, :logger => self.group_logger) }
|
16
12
|
self.groups = Hash.new
|
17
13
|
|
18
14
|
self.pid_file = File.join(self.base_dir, 'pids', self.name + ".pid")
|
@@ -118,9 +114,17 @@ module Bluepill
|
|
118
114
|
end
|
119
115
|
end
|
120
116
|
|
121
|
-
def
|
122
|
-
|
123
|
-
|
117
|
+
def quit
|
118
|
+
if @server
|
119
|
+
::Process.kill("TERM", 0)
|
120
|
+
else
|
121
|
+
send_to_server("quit")
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def add_process(process, group_name = nil)
|
126
|
+
self.groups[group_name] ||= Group.new(group_name, :logger => self.logger.prefix_with(group_name))
|
127
|
+
self.groups[group_name].add_process(process)
|
124
128
|
end
|
125
129
|
|
126
130
|
def send_to_server(method)
|
@@ -204,10 +208,10 @@ private
|
|
204
208
|
Signal.trap("INT", &terminator)
|
205
209
|
end
|
206
210
|
|
207
|
-
def grep_pattern(query)
|
208
|
-
bluepilld = '
|
209
|
-
pattern = [self.name, query].join('
|
210
|
-
[bluepilld, '\[.*', Regexp.escape(pattern), '
|
211
|
+
def grep_pattern(query = nil)
|
212
|
+
bluepilld = 'bluepilld\[[[:digit:]]+\]:[[:space:]]+'
|
213
|
+
pattern = [self.name, query].compact.join(':')
|
214
|
+
[bluepilld, '\[.*', Regexp.escape(pattern), '.*'].join
|
211
215
|
end
|
212
216
|
end
|
213
217
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Bluepill
|
2
2
|
class ConditionWatch
|
3
|
-
attr_accessor :logger
|
3
|
+
attr_accessor :logger, :name
|
4
4
|
def initialize(name, options = {})
|
5
5
|
@name = name
|
6
6
|
|
@@ -26,9 +26,9 @@ module Bluepill
|
|
26
26
|
|
27
27
|
def record_value(value)
|
28
28
|
# TODO: record value in ProcessStatistics
|
29
|
-
self.logger.info(self.to_s) if self.logger
|
30
29
|
@history[@history_index] = [value, @process_condition.check(value)]
|
31
30
|
@history_index = (@history_index + 1) % @history.size
|
31
|
+
self.logger.info(self.to_s)
|
32
32
|
end
|
33
33
|
|
34
34
|
def clear_history!
|
@@ -38,7 +38,7 @@ module Bluepill
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def fired?
|
41
|
-
@history.select {|v| !v[1]
|
41
|
+
@history.select {|v| v && !v[1]}.size >= @times[0]
|
42
42
|
end
|
43
43
|
|
44
44
|
def to_s
|
@@ -46,7 +46,8 @@ module Bluepill
|
|
46
46
|
# use (@history[(@history_index - 1)..1] + @history[0..(@history_index - 1)]).
|
47
47
|
# collect {|v| "#{v[0]}#{v[1] ? '' : '*'}"}.join(", ")
|
48
48
|
# but that's gross so... it's gonna be out of order till we figure out a better way to get it in order
|
49
|
-
@history.collect {|v| "#{v[0]}#{v[1] ? '' : '*'}"}.join(", ")
|
49
|
+
data = @history.collect {|v| "#{v[0]}#{v[1] ? '' : '*'}" if v}.compact.join(", ")
|
50
|
+
"#{@name}: [#{data}]"
|
50
51
|
end
|
51
52
|
end
|
52
53
|
end
|
data/lib/bluepill/controller.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
1
3
|
module Bluepill
|
2
4
|
class Controller
|
3
5
|
attr_accessor :base_dir, :sockets_dir, :pids_dir
|
@@ -8,6 +10,7 @@ module Bluepill
|
|
8
10
|
self.sockets_dir = File.join(base_dir, 'socks')
|
9
11
|
self.pids_dir = File.join(base_dir, 'pids')
|
10
12
|
self.applications = Hash.new
|
13
|
+
setup_dir_structure
|
11
14
|
end
|
12
15
|
|
13
16
|
def list
|
@@ -18,5 +21,13 @@ module Bluepill
|
|
18
21
|
applications[application] ||= Application.new(application, {:base_dir => base_dir})
|
19
22
|
applications[application].send(command.to_sym, *args.compact)
|
20
23
|
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def setup_dir_structure
|
28
|
+
[@sockets_dir, @pids_dir].each do |dir|
|
29
|
+
FileUtils.mkdir_p(dir) unless File.exists?(dir)
|
30
|
+
end
|
31
|
+
end
|
21
32
|
end
|
22
33
|
end
|
data/lib/bluepill/group.rb
CHANGED
@@ -7,15 +7,10 @@ module Bluepill
|
|
7
7
|
self.name = name
|
8
8
|
self.processes = []
|
9
9
|
self.logger = options[:logger]
|
10
|
-
|
11
|
-
if self.logger
|
12
|
-
logger_prefix = self.name ? "#{self.name}:" : nil
|
13
|
-
self.process_logger = Bluepill::Logger.new(self.logger, logger_prefix)
|
14
|
-
end
|
15
10
|
end
|
16
11
|
|
17
12
|
def add_process(process)
|
18
|
-
process.logger =
|
13
|
+
process.logger = self.logger.prefix_with(process.name)
|
19
14
|
self.processes << process
|
20
15
|
end
|
21
16
|
|
data/lib/bluepill/logger.rb
CHANGED
@@ -1,17 +1,29 @@
|
|
1
1
|
module Bluepill
|
2
2
|
class Logger
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
LOG_METHODS = [:emerg, :alert, :crit, :err, :warning, :notice, :info, :debug]
|
4
|
+
|
5
|
+
def initialize(options = {})
|
6
|
+
@logger = options[:logger] || Syslog.open(options[:identity] || 'bluepilld', Syslog::LOG_PID, Syslog::LOG_LOCAL6)
|
7
|
+
@prefix = options[:prefix]
|
8
|
+
@prefixes = {}
|
6
9
|
end
|
7
10
|
|
8
|
-
|
11
|
+
LOG_METHODS.each do |method|
|
9
12
|
eval <<-END
|
10
|
-
def #{method}(
|
11
|
-
|
12
|
-
|
13
|
+
def #{method}(msg, prefix = [])
|
14
|
+
if @logger.is_a?(self.class)
|
15
|
+
@logger.#{method}(msg, [@prefix] + prefix)
|
16
|
+
else
|
17
|
+
prefix = prefix.size > 0 ? "[\#{prefix.compact.join(':')}] " : ""
|
18
|
+
@logger.#{method}("\#{prefix}\#{msg}")
|
19
|
+
end
|
13
20
|
end
|
14
21
|
END
|
15
22
|
end
|
23
|
+
|
24
|
+
def prefix_with(prefix)
|
25
|
+
@prefixes[prefix] ||= self.class.new(:logger => self, :prefix => prefix)
|
26
|
+
end
|
27
|
+
|
16
28
|
end
|
17
29
|
end
|
data/lib/bluepill/process.rb
CHANGED
@@ -82,7 +82,7 @@ module Bluepill
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def add_watch(name, options = {})
|
85
|
-
self.watches << ConditionWatch.new(name, options.merge(:logger => self.
|
85
|
+
self.watches << ConditionWatch.new(name, options.merge(:logger => self.logger))
|
86
86
|
end
|
87
87
|
|
88
88
|
def daemonize?
|
@@ -90,10 +90,14 @@ module Bluepill
|
|
90
90
|
end
|
91
91
|
|
92
92
|
def dispatch!(event)
|
93
|
-
logger.info "Got stop"
|
94
93
|
self.send("#{event}!")
|
95
94
|
end
|
96
95
|
|
96
|
+
def logger=(logger)
|
97
|
+
@logger = logger
|
98
|
+
self.watches.each {|w| w.logger = logger }
|
99
|
+
end
|
100
|
+
|
97
101
|
def process_running?(force = false)
|
98
102
|
@process_running = nil if force
|
99
103
|
@process_running ||= signal_process(0)
|
@@ -158,14 +162,18 @@ module Bluepill
|
|
158
162
|
now = Time.now.to_i
|
159
163
|
|
160
164
|
threads = self.watches.collect do |watch|
|
161
|
-
Thread.new { Thread.current[:events] = watch.run(self.actual_pid, now) }
|
165
|
+
[watch, Thread.new { Thread.current[:events] = watch.run(self.actual_pid, now) }]
|
162
166
|
end
|
163
167
|
|
164
168
|
@transitioned = false
|
165
169
|
|
166
|
-
threads.inject([]) do |events, thread|
|
170
|
+
threads.inject([]) do |events, (watch, thread)|
|
167
171
|
thread.join
|
168
|
-
|
172
|
+
if thread[:events].size > 0
|
173
|
+
logger.info "#{watch.name} dispatched: #{thread[:events].join(',')}"
|
174
|
+
events << thread[:events]
|
175
|
+
end
|
176
|
+
events
|
169
177
|
end.flatten.uniq.each do |event|
|
170
178
|
break if @transitioned
|
171
179
|
self.dispatch!(event)
|
@@ -174,6 +182,7 @@ module Bluepill
|
|
174
182
|
|
175
183
|
def record_transition(state_name)
|
176
184
|
@transitioned = true
|
185
|
+
self.watches.each { |w| w.clear_history! }
|
177
186
|
# do other stuff here?
|
178
187
|
end
|
179
188
|
|
@@ -192,10 +201,6 @@ module Bluepill
|
|
192
201
|
@actual_pid = nil
|
193
202
|
File.unlink(pid_file) if File.exists?(pid_file)
|
194
203
|
end
|
195
|
-
|
196
|
-
def watch_logger
|
197
|
-
@watch_logger ||= Logger.new(self.logger, "#{self.name}:") if self.logger
|
198
|
-
end
|
199
204
|
end
|
200
205
|
end
|
201
206
|
|
data/lib/example.rb
CHANGED
@@ -19,25 +19,25 @@ ROOT_DIR = "/tmp/bp"
|
|
19
19
|
# application.start
|
20
20
|
|
21
21
|
|
22
|
-
Bluepill.application(:sample_app
|
22
|
+
Bluepill.application(:sample_app) do |app|
|
23
23
|
2.times do |i|
|
24
24
|
app.process("process_#{i}") do |process|
|
25
25
|
process.start_command = "echo 'Process #{i}' && sleep #{rand(15) + i}"
|
26
26
|
process.daemonize = true
|
27
27
|
process.pid_file = "#{ROOT_DIR}/pids/process_#{i}.pid"
|
28
28
|
|
29
|
-
process.checks :
|
29
|
+
process.checks :cpu_usage, :every => 1, :below => 1, :times => [1,4]
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
|
33
|
+
0.times do |i|
|
34
34
|
app.process("group_process_#{i}") do |process|
|
35
35
|
process.start_command = "sleep #{rand(15) + i}"
|
36
36
|
process.group = "Poopfaced"
|
37
37
|
process.daemonize = true
|
38
38
|
process.pid_file = "#{ROOT_DIR}/pids/process_#{i}.pid"
|
39
39
|
|
40
|
-
process.checks :always_true, :every =>
|
40
|
+
process.checks :always_true, :every => 10
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bluepill
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arya Asemanfar
|
@@ -73,6 +73,7 @@ files:
|
|
73
73
|
- Rakefile
|
74
74
|
- VERSION
|
75
75
|
- bin/bluepill
|
76
|
+
- bluepill.gemspec
|
76
77
|
- lib/bluepill.rb
|
77
78
|
- lib/bluepill/application.rb
|
78
79
|
- lib/bluepill/application/client.rb
|