kostya-bluepill 0.0.60.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +10 -0
- data/.rspec +1 -0
- data/DESIGN.md +10 -0
- data/Gemfile +10 -0
- data/LICENSE +22 -0
- data/README.md +305 -0
- data/Rakefile +38 -0
- data/bin/bluepill +104 -0
- data/bluepill.gemspec +37 -0
- data/examples/example.rb +87 -0
- data/examples/new_example.rb +89 -0
- data/examples/new_runit_example.rb +29 -0
- data/examples/runit_example.rb +26 -0
- data/lib/bluepill.rb +38 -0
- data/lib/bluepill/application.rb +201 -0
- data/lib/bluepill/application/client.rb +8 -0
- data/lib/bluepill/application/server.rb +23 -0
- data/lib/bluepill/condition_watch.rb +50 -0
- data/lib/bluepill/controller.rb +110 -0
- data/lib/bluepill/dsl.rb +12 -0
- data/lib/bluepill/dsl/app_proxy.rb +25 -0
- data/lib/bluepill/dsl/process_factory.rb +122 -0
- data/lib/bluepill/dsl/process_proxy.rb +44 -0
- data/lib/bluepill/group.rb +72 -0
- data/lib/bluepill/process.rb +480 -0
- data/lib/bluepill/process_conditions.rb +14 -0
- data/lib/bluepill/process_conditions/always_true.rb +18 -0
- data/lib/bluepill/process_conditions/cpu_usage.rb +19 -0
- data/lib/bluepill/process_conditions/http.rb +58 -0
- data/lib/bluepill/process_conditions/mem_usage.rb +32 -0
- data/lib/bluepill/process_conditions/process_condition.rb +22 -0
- data/lib/bluepill/process_statistics.rb +27 -0
- data/lib/bluepill/socket.rb +58 -0
- data/lib/bluepill/system.rb +236 -0
- data/lib/bluepill/trigger.rb +59 -0
- data/lib/bluepill/triggers/flapping.rb +56 -0
- data/lib/bluepill/util/rotational_array.rb +20 -0
- data/lib/bluepill/version.rb +4 -0
- data/spec/lib/bluepill/process_statistics_spec.rb +24 -0
- data/spec/lib/bluepill/system_spec.rb +36 -0
- data/spec/spec_helper.rb +19 -0
- metadata +304 -0
data/bluepill.gemspec
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
$LOAD_PATH.push File.expand_path("../lib", __FILE__)
|
4
|
+
|
5
|
+
require "bluepill/version"
|
6
|
+
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = "kostya-bluepill"
|
9
|
+
s.version = Bluepill::VERSION.dup
|
10
|
+
s.platform = Gem::Platform::RUBY
|
11
|
+
s.authors = ["Arya Asemanfar", "Gary Tsang", "Rohith Ravi"]
|
12
|
+
s.email = ["entombedvirus@gmail.com"]
|
13
|
+
s.homepage = "http://github.com/kostya/bluepill"
|
14
|
+
s.summary = %q{A process monitor written in Ruby with stability and minimalism in mind.}
|
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
|
+
|
17
|
+
s.add_dependency 'daemons', ['~> 1.1.4', '<= 1.1.6']
|
18
|
+
s.add_dependency 'state_machine', '~> 1.1.0'
|
19
|
+
s.add_dependency 'activesupport', '>= 3.0.0'
|
20
|
+
s.add_dependency 'i18n', '>= 0.5.0'
|
21
|
+
s.add_dependency 'madvertise-logging'
|
22
|
+
|
23
|
+
s.add_development_dependency 'bundler', '>= 1.0.10'
|
24
|
+
s.add_development_dependency 'rake', '!= 0.9.0'
|
25
|
+
s.add_development_dependency 'rspec-core', '~> 2.0'
|
26
|
+
s.add_development_dependency 'rspec-expectations', '~> 2.0'
|
27
|
+
s.add_development_dependency 'rr', '~> 1.0'
|
28
|
+
s.add_development_dependency 'faker', '~> 0.9'
|
29
|
+
s.add_development_dependency 'yard', '~> 0.7'
|
30
|
+
|
31
|
+
s.files = `git ls-files`.split("\n")
|
32
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
33
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
34
|
+
s.require_paths = ["lib"]
|
35
|
+
s.extra_rdoc_files = ["LICENSE", "README.md"]
|
36
|
+
end
|
37
|
+
|
data/examples/example.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bluepill'
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
ROOT_DIR = "/tmp/bp"
|
6
|
+
|
7
|
+
# Watch with
|
8
|
+
# watch -n0.2 'ps axu | egrep "(CPU|forking|bluepill|sleep)" | grep -v grep | sort'
|
9
|
+
Bluepill.application(:sample_app) do |app|
|
10
|
+
0.times do |i|
|
11
|
+
app.process("process_#{i}") do |process|
|
12
|
+
process.pid_file = "#{ROOT_DIR}/pids/process_#{i}.pid"
|
13
|
+
|
14
|
+
# Example of use of pid_command option to find memcached process
|
15
|
+
# process.pid_command = "ps -ef | awk '/memcached$/{ print $2 }'"
|
16
|
+
|
17
|
+
# I could not figure out a portable way to
|
18
|
+
# specify the path to the sample forking server across the diff developer laptops.
|
19
|
+
# Since this code is eval'ed we cannot reliably use __FILE__
|
20
|
+
process.start_command = "/Users/rohith/work/bluepill/bin/sample_forking_server #{4242 + i}"
|
21
|
+
process.stop_command = "kill -INT {{PID}}"
|
22
|
+
process.daemonize = true
|
23
|
+
|
24
|
+
process.start_grace_time = 1.seconds
|
25
|
+
process.restart_grace_time = 7.seconds
|
26
|
+
process.stop_grace_time = 7.seconds
|
27
|
+
|
28
|
+
process.uid = "rohith"
|
29
|
+
process.gid = "staff"
|
30
|
+
|
31
|
+
# process.checks :cpu_usage, :every => 10, :below => 0.5, :times => [5, 5]
|
32
|
+
process.checks :flapping, :times => 2, :within => 30.seconds, :retry_in => 7.seconds
|
33
|
+
|
34
|
+
process.monitor_children do |child_process|
|
35
|
+
# child_process.checks :cpu_usage,
|
36
|
+
# :every => 10,
|
37
|
+
# :below => 0.5,
|
38
|
+
# :times => [5, 5]
|
39
|
+
|
40
|
+
# child_process.checks :mem_usage,
|
41
|
+
# :every => 3,
|
42
|
+
# :below => 600.kilobytes,
|
43
|
+
# :times => [3, 5],
|
44
|
+
# :fires => [:stop]
|
45
|
+
|
46
|
+
child_process.stop_command = "kill -QUIT {{PID}}"
|
47
|
+
# child_process.checks :flapping, :times => 2, :within => 30.seconds, :retry_in => 7.seconds
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
0.times do |i|
|
53
|
+
app.process("group_process_#{i}") do |process|
|
54
|
+
process.group = "group_1"
|
55
|
+
process.pid_file = "/Users/rohith/ffs/tmp/pids/mongrel_#{i}.pid"
|
56
|
+
process.start_command = "cd ~/ffs && mongrel_rails start -P #{process.pid_file} -p 3000 -d"
|
57
|
+
|
58
|
+
process.start_grace_time = 10.seconds
|
59
|
+
|
60
|
+
process.uid = "rohith"
|
61
|
+
process.gid = "staff"
|
62
|
+
|
63
|
+
# process.checks :always_true, :every => 10
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
1.times do |i|
|
68
|
+
app.process("group_process_#{i}") do |process|
|
69
|
+
process.auto_start = false
|
70
|
+
|
71
|
+
process.uid = "rohith"
|
72
|
+
process.gid = "wheel"
|
73
|
+
|
74
|
+
process.stderr = "/tmp/err.log"
|
75
|
+
process.stdout = "/tmp/err.log"
|
76
|
+
|
77
|
+
|
78
|
+
process.group = "grouped"
|
79
|
+
process.start_command = %Q{cd /tmp && ruby -e '$stderr.puts("hello stderr");$stdout.puts("hello stdout"); $stdout.flush; $stderr.flush; sleep 10'}
|
80
|
+
process.daemonize = true
|
81
|
+
process.pid_file = "/tmp/noperm/p_#{process.group}_#{i}.pid"
|
82
|
+
|
83
|
+
# process.checks :always_true, :every => 5
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bluepill'
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
# Note that this syntax supported from bluepill 0.0.50
|
6
|
+
|
7
|
+
ROOT_DIR = "/tmp/bp"
|
8
|
+
|
9
|
+
# Watch with
|
10
|
+
# watch -n0.2 'ps axu | egrep "(CPU|forking|bluepill|sleep)" | grep -v grep | sort'
|
11
|
+
Bluepill.application(:sample_app) do
|
12
|
+
0.times do |i|
|
13
|
+
process("process_#{i}") do
|
14
|
+
pid_file "#{ROOT_DIR}/pids/process_#{i}.pid"
|
15
|
+
|
16
|
+
# Example of use of pid_command option to find memcached process
|
17
|
+
# pid_command = "ps -ef | awk '/memcached$/{ print $2 }'"
|
18
|
+
|
19
|
+
# I could not figure out a portable way to
|
20
|
+
# specify the path to the sample forking server across the diff developer laptops.
|
21
|
+
# Since this code is eval'ed we cannot reliably use __FILE__
|
22
|
+
start_command "/Users/rohith/work/bluepill/bin/sample_forking_server #{4242 + i}"
|
23
|
+
stop_command "kill -INT {{PID}}"
|
24
|
+
daemonize!
|
25
|
+
|
26
|
+
start_grace_time 1.seconds
|
27
|
+
restart_grace_time 7.seconds
|
28
|
+
stop_grace_time 7.seconds
|
29
|
+
|
30
|
+
uid "rohith"
|
31
|
+
gid "staff"
|
32
|
+
|
33
|
+
# checks :cpu_usage, :every => 10, :below => 0.5, :times => [5, 5]
|
34
|
+
checks :flapping, :times => 2, :within => 30.seconds, :retry_in => 7.seconds
|
35
|
+
|
36
|
+
monitor_children do
|
37
|
+
# checks :cpu_usage,
|
38
|
+
# :every => 10,
|
39
|
+
# :below => 0.5,
|
40
|
+
# :times => [5, 5]
|
41
|
+
|
42
|
+
# checks :mem_usage,
|
43
|
+
# :every => 3,
|
44
|
+
# :below => 600.kilobytes,
|
45
|
+
# :times => [3, 5],
|
46
|
+
# :fires => [:stop]
|
47
|
+
|
48
|
+
stop_command "kill -QUIT {{PID}}"
|
49
|
+
# checks :flapping, :times => 2, :within => 30.seconds, :retry_in => 7.seconds
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
0.times do |i|
|
55
|
+
process("group_process_#{i}") do
|
56
|
+
group "group_1"
|
57
|
+
pid_file "/Users/rohith/ffs/tmp/pids/mongrel_#{i}.pid"
|
58
|
+
start_command "cd ~/ffs && mongrel_rails start -P #{pid_file} -p 3000 -d"
|
59
|
+
|
60
|
+
start_grace_time 10.seconds
|
61
|
+
|
62
|
+
uid "rohith"
|
63
|
+
gid "staff"
|
64
|
+
|
65
|
+
# checks :always_true, :every => 10
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
1.times do |i|
|
70
|
+
process("group_process_#{i}") do
|
71
|
+
auto_start false
|
72
|
+
|
73
|
+
uid "rohith"
|
74
|
+
gid "wheel"
|
75
|
+
|
76
|
+
stderr "/tmp/err.log"
|
77
|
+
stdout "/tmp/err.log"
|
78
|
+
|
79
|
+
|
80
|
+
group "grouped"
|
81
|
+
start_command %Q{cd /tmp && ruby -e '$stderr.puts("hello stderr");$stdout.puts("hello stdout"); $stdout.flush; $stderr.flush; sleep 10'}
|
82
|
+
daemonize!
|
83
|
+
pid_file "/tmp/noperm/p_#{group}_#{i}.pid"
|
84
|
+
|
85
|
+
# checks :always_true, :every => 5
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'bluepill'
|
4
|
+
require 'logger'
|
5
|
+
|
6
|
+
# ATTENTION:
|
7
|
+
# You must declare only one application per config when foreground mode specified
|
8
|
+
#
|
9
|
+
# http://github.com/Undev/runit-man used as example of monitored application.
|
10
|
+
|
11
|
+
# Note that this syntax supported from bluepill 0.0.50
|
12
|
+
|
13
|
+
Bluepill.application(:runit_man, :foreground => true) do
|
14
|
+
process("runit-man") do
|
15
|
+
pid_file "/etc/service/runit-man/supervise/pid"
|
16
|
+
|
17
|
+
start_command "/usr/bin/sv start runit-man"
|
18
|
+
stop_command "/usr/bin/sv stop runit-man"
|
19
|
+
restart_command "/usr/bin/sv restart runit-man"
|
20
|
+
|
21
|
+
start_grace_time 1.seconds
|
22
|
+
restart_grace_time 7.seconds
|
23
|
+
stop_grace_time 7.seconds
|
24
|
+
|
25
|
+
checks :http, :within => 30.seconds, :retry_in => 7.seconds, :every => 30.seconds,
|
26
|
+
:url => 'http://localhost:4567/', :kind => :success, :pattern => /html/, :timeout => 3.seconds
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'bluepill'
|
4
|
+
require 'logger'
|
5
|
+
|
6
|
+
# ATTENTION:
|
7
|
+
# You must declare only one application per config when foreground mode specified
|
8
|
+
#
|
9
|
+
# http://github.com/Undev/runit-man used as example of monitored application.
|
10
|
+
|
11
|
+
Bluepill.application(:runit_man, :foreground => true) do |app|
|
12
|
+
app.process("runit-man") do |process|
|
13
|
+
process.pid_file = "/etc/service/runit-man/supervise/pid"
|
14
|
+
|
15
|
+
process.start_command = "/usr/bin/sv start runit-man"
|
16
|
+
process.stop_command = "/usr/bin/sv stop runit-man"
|
17
|
+
process.restart_command = "/usr/bin/sv restart runit-man"
|
18
|
+
|
19
|
+
process.start_grace_time = 1.seconds
|
20
|
+
process.restart_grace_time = 7.seconds
|
21
|
+
process.stop_grace_time = 7.seconds
|
22
|
+
|
23
|
+
process.checks :http, :within => 30.seconds, :retry_in => 7.seconds, :every => 30.seconds,
|
24
|
+
:url => 'http://localhost:4567/', :kind => :success, :pattern => /html/, :timeout => 3.seconds
|
25
|
+
end
|
26
|
+
end
|
data/lib/bluepill.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require 'rubygems'
|
3
|
+
|
4
|
+
require 'bundler/setup' if ENV['BUNDLE_GEMFILE'] && File.exists?(ENV['BUNDLE_GEMFILE'])
|
5
|
+
|
6
|
+
require 'thread'
|
7
|
+
require 'monitor'
|
8
|
+
require 'syslog'
|
9
|
+
require 'timeout'
|
10
|
+
|
11
|
+
require 'madvertise-logging'
|
12
|
+
|
13
|
+
require 'active_support/inflector'
|
14
|
+
require 'active_support/core_ext/hash'
|
15
|
+
require 'active_support/core_ext/numeric'
|
16
|
+
require 'active_support/duration'
|
17
|
+
|
18
|
+
require 'bluepill/dsl/process_proxy'
|
19
|
+
require 'bluepill/dsl/process_factory'
|
20
|
+
require 'bluepill/dsl/app_proxy'
|
21
|
+
|
22
|
+
require 'bluepill/application'
|
23
|
+
require 'bluepill/controller'
|
24
|
+
require 'bluepill/socket'
|
25
|
+
require "bluepill/process"
|
26
|
+
require "bluepill/process_statistics"
|
27
|
+
require "bluepill/group"
|
28
|
+
require "bluepill/condition_watch"
|
29
|
+
require 'bluepill/trigger'
|
30
|
+
require 'bluepill/triggers/flapping'
|
31
|
+
require "bluepill/dsl"
|
32
|
+
require "bluepill/system"
|
33
|
+
|
34
|
+
require "bluepill/process_conditions"
|
35
|
+
|
36
|
+
require "bluepill/util/rotational_array"
|
37
|
+
|
38
|
+
require "bluepill/version"
|
@@ -0,0 +1,201 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require 'thread'
|
3
|
+
|
4
|
+
module Bluepill
|
5
|
+
class Application
|
6
|
+
PROCESS_COMMANDS = [:start, :stop, :restart, :unmonitor, :status]
|
7
|
+
|
8
|
+
attr_accessor :name, :logger, :base_dir, :socket, :pid_file, :kill_timeout
|
9
|
+
attr_accessor :groups, :work_queue
|
10
|
+
attr_accessor :pids_dir
|
11
|
+
|
12
|
+
def initialize(name, options = {})
|
13
|
+
self.name = name
|
14
|
+
|
15
|
+
@foreground = options[:foreground]
|
16
|
+
self.base_dir = options[:base_dir] || File.join(ENV['HOME'], '.bluepill')
|
17
|
+
self.pid_file = File.join(self.base_dir, 'pids', self.name + ".pid")
|
18
|
+
self.pids_dir = File.join(self.base_dir, 'pids', self.name)
|
19
|
+
self.kill_timeout = options[:kill_timeout] || 10
|
20
|
+
|
21
|
+
self.groups = {}
|
22
|
+
|
23
|
+
self.logger = Madvertise::Logging::ImprovedLogger.new(foreground? ? :syslog : STDERR, "bluepill-#{self.name}")
|
24
|
+
|
25
|
+
self.setup_signal_traps
|
26
|
+
self.setup_pids_dir
|
27
|
+
|
28
|
+
@mutex = Mutex.new
|
29
|
+
end
|
30
|
+
|
31
|
+
def foreground?
|
32
|
+
!!@foreground
|
33
|
+
end
|
34
|
+
|
35
|
+
def mutex(&b)
|
36
|
+
@mutex.synchronize(&b)
|
37
|
+
end
|
38
|
+
|
39
|
+
def load
|
40
|
+
begin
|
41
|
+
self.start_server
|
42
|
+
rescue StandardError => e
|
43
|
+
$stderr.puts "Failed to start bluepill:"
|
44
|
+
$stderr.puts "%s `%s`" % [e.class.name, e.message]
|
45
|
+
$stderr.puts e.backtrace
|
46
|
+
exit(5)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
PROCESS_COMMANDS.each do |command|
|
51
|
+
class_eval <<-END
|
52
|
+
def #{command}(group_name = nil, process_name = nil)
|
53
|
+
self.send_to_process_or_group(:#{command}, group_name, process_name)
|
54
|
+
end
|
55
|
+
END
|
56
|
+
end
|
57
|
+
|
58
|
+
def add_process(process, group_name = nil)
|
59
|
+
group_name = group_name.to_s if group_name
|
60
|
+
|
61
|
+
self.groups[group_name] ||= Group.new(group_name, :logger => self.logger)
|
62
|
+
self.groups[group_name].add_process(process)
|
63
|
+
end
|
64
|
+
|
65
|
+
def version
|
66
|
+
Bluepill::VERSION
|
67
|
+
end
|
68
|
+
|
69
|
+
protected
|
70
|
+
def send_to_process_or_group(method, group_name, process_name)
|
71
|
+
if group_name.nil? && process_name.nil?
|
72
|
+
self.groups.values.collect do |group|
|
73
|
+
group.send(method)
|
74
|
+
end.flatten
|
75
|
+
elsif self.groups.key?(group_name)
|
76
|
+
self.groups[group_name].send(method, process_name)
|
77
|
+
elsif process_name.nil?
|
78
|
+
# they must be targeting just by process name
|
79
|
+
process_name = group_name
|
80
|
+
self.groups.values.collect do |group|
|
81
|
+
group.send(method, process_name)
|
82
|
+
end.flatten
|
83
|
+
else
|
84
|
+
[]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def start_listener
|
89
|
+
@listener_thread.kill if @listener_thread
|
90
|
+
@listener_thread = Thread.new do
|
91
|
+
loop do
|
92
|
+
begin
|
93
|
+
client = self.socket.accept
|
94
|
+
client.close_on_exec = true if client.respond_to?(:close_on_exec=)
|
95
|
+
command, *args = client.readline.strip.split(":")
|
96
|
+
response = begin
|
97
|
+
mutex { self.send(command, *args) }
|
98
|
+
rescue Exception => e
|
99
|
+
e
|
100
|
+
end
|
101
|
+
client.write(Marshal.dump(response))
|
102
|
+
rescue StandardError => e
|
103
|
+
logger.exception(e)
|
104
|
+
ensure
|
105
|
+
begin
|
106
|
+
client.close
|
107
|
+
rescue IOError
|
108
|
+
# closed stream
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def start_server
|
116
|
+
self.kill_previous_bluepill
|
117
|
+
|
118
|
+
Daemonize.daemonize unless foreground?
|
119
|
+
|
120
|
+
$0 = "bluepill: #{self.name}"
|
121
|
+
|
122
|
+
self.groups.each {|_, group| group.determine_initial_state }
|
123
|
+
|
124
|
+
|
125
|
+
self.write_pid_file
|
126
|
+
self.socket = Bluepill::Socket.server(self.base_dir, self.name)
|
127
|
+
self.start_listener
|
128
|
+
|
129
|
+
self.run
|
130
|
+
end
|
131
|
+
|
132
|
+
def run
|
133
|
+
@running = true # set to false by signal trap
|
134
|
+
while @running
|
135
|
+
mutex do
|
136
|
+
System.reset_data
|
137
|
+
self.groups.each { |_, group| group.tick }
|
138
|
+
end
|
139
|
+
sleep 1
|
140
|
+
end
|
141
|
+
cleanup
|
142
|
+
end
|
143
|
+
|
144
|
+
def cleanup
|
145
|
+
File.unlink(self.socket.path) if self.socket
|
146
|
+
File.unlink(self.pid_file) if File.exists?(self.pid_file)
|
147
|
+
end
|
148
|
+
|
149
|
+
def setup_signal_traps
|
150
|
+
terminator = Proc.new do
|
151
|
+
puts "Terminating..."
|
152
|
+
@running = false
|
153
|
+
end
|
154
|
+
|
155
|
+
Signal.trap("TERM", &terminator)
|
156
|
+
Signal.trap("INT", &terminator)
|
157
|
+
|
158
|
+
Signal.trap("HUP") do
|
159
|
+
self.logger.close if self.logger
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def setup_pids_dir
|
164
|
+
FileUtils.mkdir_p(self.pids_dir) unless File.exists?(self.pids_dir)
|
165
|
+
# we need everybody to be able to write to the pids_dir as processes managed by
|
166
|
+
# bluepill will be writing to this dir after they've dropped privileges
|
167
|
+
FileUtils.chmod(0777, self.pids_dir)
|
168
|
+
end
|
169
|
+
|
170
|
+
def kill_previous_bluepill
|
171
|
+
if File.exists?(self.pid_file)
|
172
|
+
previous_pid = File.read(self.pid_file).to_i
|
173
|
+
if System.pid_alive?(previous_pid)
|
174
|
+
begin
|
175
|
+
::Process.kill(0, previous_pid)
|
176
|
+
puts "Killing previous bluepill[#{previous_pid}]"
|
177
|
+
::Process.kill(2, previous_pid)
|
178
|
+
rescue Exception => e
|
179
|
+
$stderr.puts "Encountered error trying to kill previous bluepill:"
|
180
|
+
$stderr.puts "#{e.class}: #{e.message}"
|
181
|
+
exit(4) unless e.is_a?(Errno::ESRCH)
|
182
|
+
else
|
183
|
+
kill_timeout.times do |i|
|
184
|
+
sleep 0.5
|
185
|
+
break unless System.pid_alive?(previous_pid)
|
186
|
+
end
|
187
|
+
|
188
|
+
if System.pid_alive?(previous_pid)
|
189
|
+
$stderr.puts "Previous bluepill[#{previous_pid}] didn't die"
|
190
|
+
exit(4)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def write_pid_file
|
198
|
+
File.open(self.pid_file, 'w') { |x| x.write(::Process.pid) }
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|