bluepill 0.0.28 → 0.0.30
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/bluepill.gemspec +3 -2
- data/lib/bluepill.rb +1 -0
- data/lib/bluepill/application.rb +1 -44
- data/lib/bluepill/controller.rb +2 -2
- data/lib/bluepill/dsl.rb +5 -0
- data/lib/bluepill/group.rb +25 -0
- data/lib/bluepill/process.rb +12 -8
- data/lib/bluepill/process_conditions/process_condition.rb +4 -0
- data/lib/bluepill/process_statistics.rb +24 -0
- data/lib/bluepill/trigger.rb +2 -2
- data/lib/bluepill/util/rotational_array.rb +8 -0
- data/lib/bluepill/version.rb +1 -1
- data/lib/example.rb +16 -3
- metadata +3 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.30
|
data/bluepill.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{bluepill}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.30"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Arya Asemanfar", "Gary Tsang", "Rohith Ravi"]
|
12
|
-
s.date = %q{2009-12-
|
12
|
+
s.date = %q{2009-12-27}
|
13
13
|
s.default_executable = %q{bluepill}
|
14
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
15
|
s.email = %q{entombedvirus@gmail.com}
|
@@ -43,6 +43,7 @@ Gem::Specification.new do |s|
|
|
43
43
|
"lib/bluepill/process_conditions/cpu_usage.rb",
|
44
44
|
"lib/bluepill/process_conditions/mem_usage.rb",
|
45
45
|
"lib/bluepill/process_conditions/process_condition.rb",
|
46
|
+
"lib/bluepill/process_statistics.rb",
|
46
47
|
"lib/bluepill/socket.rb",
|
47
48
|
"lib/bluepill/system.rb",
|
48
49
|
"lib/bluepill/trigger.rb",
|
data/lib/bluepill.rb
CHANGED
data/lib/bluepill/application.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Bluepill
|
2
2
|
class Application
|
3
|
-
PROCESS_COMMANDS = [:start, :stop, :restart, :unmonitor]
|
3
|
+
PROCESS_COMMANDS = [:start, :stop, :restart, :unmonitor, :status]
|
4
4
|
|
5
5
|
attr_accessor :name, :logger, :base_dir, :socket, :pid_file
|
6
6
|
attr_accessor :groups, :work_queue
|
@@ -33,49 +33,6 @@ module Bluepill
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
def status
|
37
|
-
buffer = []
|
38
|
-
depth = 0
|
39
|
-
|
40
|
-
if self.groups.has_key?(nil)
|
41
|
-
self.groups[nil].processes.each do |p|
|
42
|
-
buffer << "%s%s(pid:%s): %s" % [" " * depth, p.name, p.actual_pid.inspect, p.state]
|
43
|
-
|
44
|
-
if p.monitor_children?
|
45
|
-
depth += 2
|
46
|
-
p.children.each do |c|
|
47
|
-
buffer << "%s%s: %s" % [" " * depth, c.name, c.state]
|
48
|
-
end
|
49
|
-
depth -= 2
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
self.groups.each do |group_name, group|
|
55
|
-
next if group_name.nil?
|
56
|
-
|
57
|
-
buffer << "\n#{group_name}"
|
58
|
-
|
59
|
-
group.processes.each do |p|
|
60
|
-
depth += 2
|
61
|
-
|
62
|
-
buffer << "%s%s(pid:%s): %s" % [" " * depth, p.name, p.actual_pid.inspect, p.state]
|
63
|
-
|
64
|
-
if p.monitor_children?
|
65
|
-
depth += 2
|
66
|
-
p.children.each do |c|
|
67
|
-
buffer << "%s%s: %s" % [" " * depth, c.name, c.state]
|
68
|
-
end
|
69
|
-
depth -= 2
|
70
|
-
end
|
71
|
-
|
72
|
-
depth -= 2
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
buffer.join("\n")
|
77
|
-
end
|
78
|
-
|
79
36
|
PROCESS_COMMANDS.each do |command|
|
80
37
|
class_eval <<-END
|
81
38
|
def #{command}(group_name = nil, process_name = nil)
|
data/lib/bluepill/controller.rb
CHANGED
@@ -20,6 +20,8 @@ module Bluepill
|
|
20
20
|
|
21
21
|
def handle_command(application, command, *args)
|
22
22
|
case command.to_sym
|
23
|
+
when :status
|
24
|
+
puts self.send_to_daemon(application, :status, *args)
|
23
25
|
when *Application::PROCESS_COMMANDS
|
24
26
|
# these need to be sent to the daemon and the results printed out
|
25
27
|
affected = self.send_to_daemon(application, command, *args)
|
@@ -31,8 +33,6 @@ module Bluepill
|
|
31
33
|
puts " #{process}"
|
32
34
|
end
|
33
35
|
end
|
34
|
-
when :status
|
35
|
-
puts self.send_to_daemon(application, :status, *args)
|
36
36
|
when :quit
|
37
37
|
pid = pid_for(application)
|
38
38
|
if System.pid_alive?(pid)
|
data/lib/bluepill/dsl.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
require 'ostruct'
|
2
2
|
module Bluepill
|
3
|
+
def self.define_process_condition(name, &block)
|
4
|
+
klass = Class.new(ProcessConditions::ProcessCondition, &block)
|
5
|
+
ProcessConditions.const_set("#{name.to_s.camelcase}", klass)
|
6
|
+
end
|
7
|
+
|
3
8
|
def self.application(app_name, options = {}, &block)
|
4
9
|
app = Application.new(app_name.to_s, options, &block)
|
5
10
|
|
data/lib/bluepill/group.rb
CHANGED
@@ -36,5 +36,30 @@ module Bluepill
|
|
36
36
|
end
|
37
37
|
END
|
38
38
|
end
|
39
|
+
|
40
|
+
def status(process_name = nil)
|
41
|
+
lines = []
|
42
|
+
if process_name.nil?
|
43
|
+
prefix = self.name ? " " : ""
|
44
|
+
lines << "#{self.name}:" if self.name
|
45
|
+
|
46
|
+
self.processes.each do |process|
|
47
|
+
lines << "%s%s(pid:%s): %s" % [prefix, process.name, process.actual_pid, process.state]
|
48
|
+
if process.monitor_children?
|
49
|
+
process.children.each do |child|
|
50
|
+
lines << " %s%s: %s" % [prefix, child.name, child.state]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
else
|
55
|
+
self.processes.each do |process|
|
56
|
+
next if process_name != process.name
|
57
|
+
lines << "%s%s(pid:%s): %s" % [prefix, process.name, process.actual_pid, process.state]
|
58
|
+
lines << process.statistics.to_s
|
59
|
+
end
|
60
|
+
end
|
61
|
+
lines << ""
|
62
|
+
end
|
63
|
+
|
39
64
|
end
|
40
65
|
end
|
data/lib/bluepill/process.rb
CHANGED
@@ -29,7 +29,7 @@ module Bluepill
|
|
29
29
|
|
30
30
|
attr_accessor :name, :watches, :triggers, :logger, :skip_ticks_until
|
31
31
|
attr_accessor *CONFIGURABLE_ATTRIBUTES
|
32
|
-
attr_reader :children
|
32
|
+
attr_reader :children, :statistics
|
33
33
|
|
34
34
|
state_machine :initial => :unmonitored do
|
35
35
|
# These are the idle states, i.e. only an event (either external or internal) will trigger a transition.
|
@@ -91,6 +91,7 @@ module Bluepill
|
|
91
91
|
@watches = []
|
92
92
|
@triggers = []
|
93
93
|
@children = []
|
94
|
+
@statistics = ProcessStatistics.new
|
94
95
|
|
95
96
|
@monitor_children = options[:monitor_children] || false
|
96
97
|
|
@@ -133,8 +134,9 @@ module Bluepill
|
|
133
134
|
end
|
134
135
|
|
135
136
|
# State machine methods
|
136
|
-
def dispatch!(event)
|
137
|
+
def dispatch!(event, reason = nil)
|
137
138
|
@event_mutex.synchronize do
|
139
|
+
@statistics.record_event(event, reason)
|
138
140
|
self.send("#{event}")
|
139
141
|
end
|
140
142
|
end
|
@@ -181,12 +183,14 @@ module Bluepill
|
|
181
183
|
thread.join
|
182
184
|
if thread[:events].size > 0
|
183
185
|
logger.info "#{watch.name} dispatched: #{thread[:events].join(',')}"
|
184
|
-
|
186
|
+
thread[:events].each do |event|
|
187
|
+
events << [event, watch.to_s]
|
188
|
+
end
|
185
189
|
end
|
186
190
|
events
|
187
|
-
end.
|
191
|
+
end.each do |(event, reason)|
|
188
192
|
break if @transitioned
|
189
|
-
self.dispatch!(event)
|
193
|
+
self.dispatch!(event, reason)
|
190
194
|
end
|
191
195
|
end
|
192
196
|
|
@@ -206,11 +210,11 @@ module Bluepill
|
|
206
210
|
logger.warning("Refusing to re-run start command on an automatically daemonized process to preserve currently running process pid file.")
|
207
211
|
return
|
208
212
|
end
|
209
|
-
dispatch!(:start)
|
213
|
+
dispatch!(:start, "user initiated")
|
210
214
|
|
211
215
|
when "stop"
|
212
216
|
stop_process
|
213
|
-
dispatch!(:unmonitor)
|
217
|
+
dispatch!(:unmonitor, "user initiated")
|
214
218
|
|
215
219
|
when "restart"
|
216
220
|
restart_process
|
@@ -219,7 +223,7 @@ module Bluepill
|
|
219
223
|
# When the user issues an unmonitor cmd, reset any triggers so that
|
220
224
|
# scheduled events gets cleared
|
221
225
|
triggers.each {|t| t.reset! }
|
222
|
-
dispatch!(:unmonitor)
|
226
|
+
dispatch!(:unmonitor, "user initiated")
|
223
227
|
end
|
224
228
|
end
|
225
229
|
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Bluepill
|
2
|
+
class ProcessStatistics
|
3
|
+
STRFTIME = "%m/%d/%Y %H:%I:%S"
|
4
|
+
# possibly persist this data.
|
5
|
+
def initialize
|
6
|
+
@events = Util::RotationalArray.new(10)
|
7
|
+
end
|
8
|
+
|
9
|
+
def record_event(event, reason)
|
10
|
+
@events.push([event, reason, Time.now])
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
str = []
|
15
|
+
@events.each do |(event, reason, time)|
|
16
|
+
str << " #{event} at #{time.strftime(STRFTIME)} - #{reason || "unspecified"}"
|
17
|
+
end
|
18
|
+
if str.size > 0
|
19
|
+
str << "event history:"
|
20
|
+
end
|
21
|
+
str.reverse.join("\n")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/bluepill/trigger.rb
CHANGED
@@ -27,7 +27,7 @@ module Bluepill
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def dispatch!(event)
|
30
|
-
self.process.dispatch!(event)
|
30
|
+
self.process.dispatch!(event, self.class.name.split("::").last)
|
31
31
|
end
|
32
32
|
|
33
33
|
def schedule_event(event, delay)
|
@@ -36,7 +36,7 @@ module Bluepill
|
|
36
36
|
begin
|
37
37
|
sleep delay.to_f
|
38
38
|
trigger.logger.info("Retrying from flapping")
|
39
|
-
trigger.
|
39
|
+
trigger.dispatch!(event)
|
40
40
|
trigger.mutex.synchronize do
|
41
41
|
trigger.scheduled_events.delete_if { |_, thread| thread == Thread.current }
|
42
42
|
end
|
@@ -48,6 +48,14 @@ module Bluepill
|
|
48
48
|
super
|
49
49
|
end
|
50
50
|
|
51
|
+
def each(&block)
|
52
|
+
times = @counter >= @capacity ? @capacity : @counter
|
53
|
+
start = @counter >= @capacity ? rotational_idx(@counter) : 0
|
54
|
+
times.times do |i|
|
55
|
+
block.call(self[rotational_idx(start + i)])
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
51
59
|
private
|
52
60
|
|
53
61
|
def rotational_idx(idx)
|
data/lib/bluepill/version.rb
CHANGED
data/lib/example.rb
CHANGED
@@ -3,6 +3,16 @@ require 'bluepill'
|
|
3
3
|
require 'logger'
|
4
4
|
|
5
5
|
ROOT_DIR = "/tmp/bp"
|
6
|
+
Bluepill.define_process_condition(:random_watch) do
|
7
|
+
def run(pid)
|
8
|
+
(rand * 100).to_i / 100.0
|
9
|
+
end
|
10
|
+
|
11
|
+
def check(value)
|
12
|
+
value > @options[:fails_at]
|
13
|
+
false
|
14
|
+
end
|
15
|
+
end
|
6
16
|
|
7
17
|
# Watch with
|
8
18
|
# watch -n0.2 'ps axu | egrep "(CPU|forking|bluepill|sleep)" | grep -v grep | sort'
|
@@ -61,7 +71,7 @@ Bluepill.application(:sample_app) do |app|
|
|
61
71
|
end
|
62
72
|
end
|
63
73
|
|
64
|
-
|
74
|
+
2.times do |i|
|
65
75
|
app.process("group_process_#{i}") do |process|
|
66
76
|
process.uid = "arya"
|
67
77
|
process.gid = "wheel"
|
@@ -71,11 +81,14 @@ Bluepill.application(:sample_app) do |app|
|
|
71
81
|
|
72
82
|
|
73
83
|
process.group = "grouped"
|
74
|
-
process.start_command = %Q{cd /tmp && ruby -e '$stderr.puts("hello stderr");$stdout.puts("hello stdout"); $stdout.flush; $stderr.flush; sleep 10'}
|
84
|
+
# process.start_command = %Q{cd /tmp && ruby -e '$stderr.puts("hello stderr");$stdout.puts("hello stdout"); $stdout.flush; $stderr.flush; sleep 10'}
|
85
|
+
process.start_command = "sleep 20"
|
86
|
+
process.stop_command = "kill {{PID}}"
|
75
87
|
process.daemonize = true
|
76
88
|
process.pid_file = "/tmp/p_#{process.group}_#{i}.pid"
|
77
89
|
|
78
|
-
|
90
|
+
process.checks :random_watch, :every => 2, :fails_at => 0.5
|
91
|
+
process.checks :flapping, :times => 2, :within => 900.seconds, :retry_in => 7.seconds
|
79
92
|
end
|
80
93
|
end
|
81
94
|
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.30
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arya Asemanfar
|
@@ -11,7 +11,7 @@ autorequire:
|
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
13
|
|
14
|
-
date: 2009-12-
|
14
|
+
date: 2009-12-27 00:00:00 -08:00
|
15
15
|
default_executable: bluepill
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
@@ -88,6 +88,7 @@ files:
|
|
88
88
|
- lib/bluepill/process_conditions/cpu_usage.rb
|
89
89
|
- lib/bluepill/process_conditions/mem_usage.rb
|
90
90
|
- lib/bluepill/process_conditions/process_condition.rb
|
91
|
+
- lib/bluepill/process_statistics.rb
|
91
92
|
- lib/bluepill/socket.rb
|
92
93
|
- lib/bluepill/system.rb
|
93
94
|
- lib/bluepill/trigger.rb
|