keep_running 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/keep_running +7 -0
- data/lib/keep_running.rb +115 -0
- data/lib/keep_running/version.rb +3 -0
- metadata +66 -0
data/bin/keep_running
ADDED
data/lib/keep_running.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'pony'
|
3
|
+
|
4
|
+
class KeepRunning
|
5
|
+
class << self
|
6
|
+
def load_runner(runner)
|
7
|
+
load @runner_location = runner
|
8
|
+
end
|
9
|
+
|
10
|
+
def runner_location
|
11
|
+
@runner_location ||= File.expand_path($0)
|
12
|
+
end
|
13
|
+
|
14
|
+
def process_argv
|
15
|
+
ARGV.shift if File.basename($0) == 'keep_running'
|
16
|
+
end
|
17
|
+
|
18
|
+
def run(&block)
|
19
|
+
runner = new
|
20
|
+
process_argv
|
21
|
+
runner.instance_eval &block
|
22
|
+
runner.run
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def pidfile(p) ; @pidfile = p ; end
|
27
|
+
def email(e) ; @email_opts = e ; end
|
28
|
+
def restart_threshold(t) ; @restart_threshold = t ; end
|
29
|
+
def restart_delay(d) ; @restart_delay = d ; end
|
30
|
+
def process(p)
|
31
|
+
@process = File.expand_path(File.join(File.dirname(self.class.runner_location), p))
|
32
|
+
end
|
33
|
+
|
34
|
+
def run
|
35
|
+
write_pidfile
|
36
|
+
|
37
|
+
output = nil
|
38
|
+
loop do
|
39
|
+
output = spawn { start_process } # load the given script
|
40
|
+
send_mail subject(@process), output # send the email
|
41
|
+
throttle_restart # don't restart too fast
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def start_process
|
48
|
+
if File.extname(@process) == '.rb'
|
49
|
+
load @process
|
50
|
+
else
|
51
|
+
puts 'only spawning of ruby processes supported'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def add_exit_hook(pid)
|
56
|
+
at_exit do
|
57
|
+
Process.kill 'QUIT', pid rescue nil # ensure the child exits
|
58
|
+
sleep 1 # give it some time
|
59
|
+
Process.kill 'KILL', pid rescue nil # really ensure the child exits
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def send_mail(subject, body)
|
64
|
+
Pony.mail @email_opts.update(:subject => subject(@process), :body => body)
|
65
|
+
end
|
66
|
+
|
67
|
+
def write_pidfile
|
68
|
+
puts "wrote PID-file #{@pidfile}"
|
69
|
+
File.open(@pidfile, 'w'){|file| file << Process.pid }
|
70
|
+
at_exit{
|
71
|
+
if File.new(@pidfile, "r").gets.to_i == Process.pid
|
72
|
+
FileUtils.rm @pidfile rescue nil
|
73
|
+
end
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
def spawn
|
78
|
+
readme, writeme = IO.pipe # open an pipe for the child to write in, the parent to read
|
79
|
+
pid = fork{ |variable| # fork the process
|
80
|
+
$stdout.reopen writeme # reopen the child end of the pipe
|
81
|
+
$stderr.reopen writeme # reopen the child end of the pipe
|
82
|
+
readme.close # close the parent end of the pipe in the child
|
83
|
+
yield # YIELD the given block
|
84
|
+
}
|
85
|
+
writeme.close # close the child end of the pipe in the parent
|
86
|
+
puts "forked child as PID #{pid}"
|
87
|
+
|
88
|
+
add_exit_hook pid
|
89
|
+
|
90
|
+
output = []
|
91
|
+
readme.each{ |line|
|
92
|
+
output = output[-1000,1000] || [] # truncate the output array
|
93
|
+
puts line
|
94
|
+
output << line # collect the childs stdout
|
95
|
+
}
|
96
|
+
|
97
|
+
Process.waitpid pid, 0 # wait for the child to exit
|
98
|
+
return output.join
|
99
|
+
end
|
100
|
+
|
101
|
+
def throttle_restart
|
102
|
+
if @last_exit && Time.now - @last_exit < @restart_threshold
|
103
|
+
puts "Last restart was less than #{@restart_threshold} seconds ago: #{@last_exit}."
|
104
|
+
puts "Sleeping some #{@restart_delay} seconds..."
|
105
|
+
sleep @restart_delay
|
106
|
+
puts "Let's try again."
|
107
|
+
end
|
108
|
+
@last_exit = Time.now
|
109
|
+
end
|
110
|
+
|
111
|
+
def subject(script)
|
112
|
+
"#{script} ended (PID #{Process.pid} on #{`hostname`.strip})"
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
metadata
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: keep_running
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.4
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Niko Dittmann
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-12-13 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: pony
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
type: :runtime
|
25
|
+
version_requirements: *id001
|
26
|
+
description: a script to restart other scripts whenever they crash, stop, get killed. It sends emails, when restart occurs.
|
27
|
+
email: mail+git@niko-dittmann.com
|
28
|
+
executables:
|
29
|
+
- keep_running
|
30
|
+
extensions: []
|
31
|
+
|
32
|
+
extra_rdoc_files: []
|
33
|
+
|
34
|
+
files:
|
35
|
+
- lib/keep_running/version.rb
|
36
|
+
- lib/keep_running.rb
|
37
|
+
- bin/keep_running
|
38
|
+
homepage: http://github.com/niko/keep_running
|
39
|
+
licenses: []
|
40
|
+
|
41
|
+
post_install_message:
|
42
|
+
rdoc_options: []
|
43
|
+
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
none: false
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: "0"
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: "0"
|
58
|
+
requirements: []
|
59
|
+
|
60
|
+
rubyforge_project:
|
61
|
+
rubygems_version: 1.8.11
|
62
|
+
signing_key:
|
63
|
+
specification_version: 3
|
64
|
+
summary: a script to restart other scripts whenever they crash, stop, get killed.
|
65
|
+
test_files: []
|
66
|
+
|