bannister 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +10 -1
- data/lib/bannister/apache.rb +8 -1
- data/lib/bannister/recurse.rb +20 -8
- data/lib/bannister/version.rb +1 -1
- data/lib/bannister.rb +74 -1
- metadata +21 -8
data/Rakefile
CHANGED
@@ -3,6 +3,8 @@ CLEAN << ".yardoc"
|
|
3
3
|
CLEAN << FileList["*.gem"]
|
4
4
|
CLEAN << "doc"
|
5
5
|
|
6
|
+
DOC_FILES=Dir['*.md']
|
7
|
+
|
6
8
|
desc "Build the gem"
|
7
9
|
task :gem do
|
8
10
|
system "gem build bannister.gemspec"
|
@@ -10,5 +12,12 @@ end
|
|
10
12
|
|
11
13
|
desc "Build the YARD docs"
|
12
14
|
task :docs do
|
13
|
-
system "yardoc"
|
15
|
+
system "yardoc --files #{DOC_FILES.join(",")}"
|
16
|
+
end
|
17
|
+
|
18
|
+
task :doc => :docs
|
19
|
+
|
20
|
+
desc "Build the YARD developer docs, including private methods"
|
21
|
+
task :dev_docs do
|
22
|
+
system "yardoc --private --files #{DOC_FILES.join(",")}"
|
14
23
|
end
|
data/lib/bannister/apache.rb
CHANGED
@@ -27,10 +27,13 @@ module Bannister
|
|
27
27
|
catch :done do
|
28
28
|
20.times do
|
29
29
|
sleep(0.1)
|
30
|
+
# No need to trap error messages here, because `kill`
|
31
|
+
# gives us a meaningful error code
|
30
32
|
next if system "kill -0 #{pid} 2> /dev/null"
|
31
33
|
throw :done
|
32
34
|
end
|
33
|
-
|
35
|
+
|
36
|
+
raise "Apache2 (pid=#{pid}) failed to stop!"
|
34
37
|
end
|
35
38
|
end
|
36
39
|
end
|
@@ -80,6 +83,10 @@ module Bannister
|
|
80
83
|
|
81
84
|
private
|
82
85
|
|
86
|
+
# Read apache2's pid from {PidFilename}.
|
87
|
+
#
|
88
|
+
# @return [Integer] Apache's process id.
|
89
|
+
# @return nil if it's not there.
|
83
90
|
def read_pid()
|
84
91
|
if File.file?(PidFilename)
|
85
92
|
return Integer(File.read(PidFilename).strip)
|
data/lib/bannister/recurse.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Bannister
|
2
2
|
|
3
|
-
# Use the Recurse class to launch other
|
3
|
+
# Use the Recurse class to launch other apps with a runner script.
|
4
4
|
class Recurse
|
5
5
|
|
6
6
|
# @param [String] dir Directory to chdir to before running bannister
|
@@ -10,25 +10,37 @@ module Bannister
|
|
10
10
|
@dir=dir
|
11
11
|
end
|
12
12
|
|
13
|
-
|
14
|
-
# Run "
|
13
|
+
|
14
|
+
# Run "runner stop" and exit.
|
15
15
|
def stop
|
16
|
-
system "
|
16
|
+
system "./runner stop"
|
17
17
|
exit(0)
|
18
18
|
end
|
19
19
|
|
20
20
|
|
21
|
-
# If foreground is true, exec
|
22
|
-
#
|
21
|
+
# Run the application's runner. If foreground is true, exec
|
22
|
+
# "runner run" in @dir. Otherwise set up traps for the right
|
23
|
+
# signals to a backgrounded "runner start" process.
|
24
|
+
#
|
25
|
+
# @param [Boolean] foreground Pass true to run in the foreground, false
|
26
|
+
# otherwise.
|
23
27
|
def start(foreground=false)
|
24
28
|
Dir.chdir(@dir) do
|
25
29
|
if foreground
|
26
|
-
|
30
|
+
# We're replacing the current process with the child, so we want
|
31
|
+
# std* to go to the console
|
32
|
+
exec "./runner run"
|
27
33
|
else
|
28
34
|
trap("TERM"){stop()}
|
29
35
|
trap("HUP"){stop()}
|
30
36
|
|
31
|
-
|
37
|
+
# This ignores stdout and stderr. Since the child process expects to
|
38
|
+
# running in the background anyway, we expect it to make its own
|
39
|
+
# arrangements.
|
40
|
+
#
|
41
|
+
# Yes, this is lazy, but there's not a lot more we can do at this
|
42
|
+
# point without a higher-level error-handling facility.
|
43
|
+
system "./runner start &"
|
32
44
|
|
33
45
|
sleep()
|
34
46
|
end
|
data/lib/bannister/version.rb
CHANGED
data/lib/bannister.rb
CHANGED
@@ -3,8 +3,17 @@ require 'fileutils'
|
|
3
3
|
module Bannister
|
4
4
|
|
5
5
|
|
6
|
+
# List of scripts in script/startup sorted asciibetically. This is the order
|
7
|
+
# they will be launched in, but there is no further dependency checking
|
8
|
+
# between the scripts.
|
6
9
|
SCRIPTS = Dir['script/startup/*'].sort
|
10
|
+
|
11
|
+
# A list of pids of the started scripts. These will be sent TERM signals when
|
12
|
+
# bannister is stopped.
|
7
13
|
LAUNCHED_PIDS = []
|
14
|
+
|
15
|
+
# The location of the pidfile for the master process. This will be
|
16
|
+
# de-hard-coded in a future release.
|
8
17
|
PID_FILENAME = "pids/bannister.pid"
|
9
18
|
|
10
19
|
|
@@ -42,7 +51,6 @@ module Bannister
|
|
42
51
|
else # create it. The easiest way to do this is to write
|
43
52
|
# out a screenrc containing the relevant commands and
|
44
53
|
# let screen launch them
|
45
|
-
|
46
54
|
begin
|
47
55
|
write_screenrc(screenrc_filename)
|
48
56
|
|
@@ -90,18 +98,37 @@ module Bannister
|
|
90
98
|
end
|
91
99
|
|
92
100
|
|
101
|
+
|
93
102
|
private
|
103
|
+
# Method to see whether a bannister process for the current application
|
104
|
+
# is running or not.
|
105
|
+
#
|
106
|
+
# @return [Boolean] true if PID_FILENAME exists, false otherwise.
|
94
107
|
def running?
|
95
108
|
return File.exists?(PID_FILENAME)
|
96
109
|
end
|
97
110
|
|
98
111
|
|
112
|
+
# Generate the screen command for the passed script filename. Since this
|
113
|
+
# will only ever be called when running in the foreground, we append -X
|
114
|
+
# to the command. A title for the screen window is also generated based
|
115
|
+
# on the current directory name and the script filename.
|
116
|
+
#
|
117
|
+
# @param [String] script the filename of a script to run.
|
118
|
+
# @return [String] the screen command to run the script.
|
99
119
|
def command_for_script(script)
|
100
120
|
title = File.basename(FileUtils.pwd)+':'+File.basename(script)
|
101
121
|
return "screen -t '#{title}' #{script} -X"
|
102
122
|
end
|
103
123
|
|
104
124
|
|
125
|
+
# Generate a screen config file and save it to the passed screenrc_filename.
|
126
|
+
# Screen is set up to allow restarting of dead processes with the 'r' key,
|
127
|
+
# and to give each script a meaningful title in the status line.
|
128
|
+
#
|
129
|
+
# @param [String] screenrc_filename the filename to save the
|
130
|
+
# generated config file to.
|
131
|
+
# @return [NilClass] nil.
|
105
132
|
def write_screenrc(screenrc_filename)
|
106
133
|
File.open(screenrc_filename, "wb") do |f|
|
107
134
|
f.write <<-SCREENRC
|
@@ -113,10 +140,18 @@ SCREENRC
|
|
113
140
|
f.puts( command_for_script(script) )
|
114
141
|
end
|
115
142
|
end
|
143
|
+
|
144
|
+
return nil
|
116
145
|
end
|
117
146
|
|
118
147
|
|
119
148
|
|
149
|
+
# Daemonize the bannister process and yield. Used when running in
|
150
|
+
# the background. This is a slightly different daemonize method to
|
151
|
+
# the usual, in that we need to be sure that the script filenames in
|
152
|
+
# SCRIPT don't lose their relative location, so we chdir to '/'
|
153
|
+
# *after* kicking them off. It's each individual script's
|
154
|
+
# responsibility to daemonise properly.
|
120
155
|
def daemonize()
|
121
156
|
exit!(0) if fork
|
122
157
|
Process::setsid
|
@@ -132,25 +167,43 @@ SCREENRC
|
|
132
167
|
# and if any of them rely on relative paths, they won't get
|
133
168
|
# broken
|
134
169
|
Dir::chdir("/")
|
170
|
+
|
171
|
+
return nil
|
135
172
|
end
|
136
173
|
|
137
174
|
|
175
|
+
# Set up our environment and launch everything in the background.
|
138
176
|
def do_start()
|
139
177
|
set_name()
|
140
178
|
drop_pid()
|
141
179
|
launch_all()
|
142
180
|
end
|
143
181
|
|
182
|
+
# Set the process name to something meaningful. In this case,
|
183
|
+
# "something meaningful" means "bannister:" + the name of the
|
184
|
+
# directory we're in. This makes it easy to see which bannister pids
|
185
|
+
# are responsible for which applications.
|
186
|
+
#
|
187
|
+
# @return [NilClass] nil.
|
144
188
|
def set_name
|
145
189
|
$0 = "bannister:"+File.basename(FileUtils.pwd)
|
190
|
+
|
191
|
+
return nil
|
146
192
|
end
|
147
193
|
|
194
|
+
# Record the current pid somewhere it can be found later
|
148
195
|
def drop_pid
|
149
196
|
system "mkdir -p #{File.dirname PID_FILENAME}"
|
150
197
|
File.open(PID_FILENAME, "w"){|f| f.write $$.to_s}
|
198
|
+
|
199
|
+
return nil
|
151
200
|
end
|
152
201
|
|
153
202
|
|
203
|
+
# Read the pid from where drop_pid left it, or nil if it's not there.
|
204
|
+
#
|
205
|
+
# @return [Fixnum] pid as integer if it exists
|
206
|
+
# @return [NilClass] nil otherwise.
|
154
207
|
def read_pid
|
155
208
|
if File.exists?(PID_FILENAME)
|
156
209
|
return Integer(File.read(PID_FILENAME).strip)
|
@@ -160,31 +213,51 @@ SCREENRC
|
|
160
213
|
end
|
161
214
|
|
162
215
|
|
216
|
+
# Clear the pid that drop_pid left behind.
|
217
|
+
#
|
218
|
+
# @return [NilClass] nil.
|
163
219
|
def remove_pid
|
164
220
|
FileUtils.rm_f(PID_FILENAME)
|
221
|
+
|
222
|
+
return nil
|
165
223
|
end
|
166
224
|
|
167
225
|
|
226
|
+
# Fork and exec each of SCRIPTS.
|
227
|
+
#
|
228
|
+
# @return [NilClass] nil.
|
168
229
|
def launch_all()
|
169
230
|
SCRIPTS.each do |script|
|
170
231
|
LAUNCHED_PIDS << fork do
|
171
232
|
exec script
|
172
233
|
end
|
173
234
|
end
|
235
|
+
|
236
|
+
return nil
|
174
237
|
end
|
175
238
|
|
176
239
|
|
240
|
+
# Call Process.waitpid on each process launched by launch_all.
|
241
|
+
#
|
242
|
+
# @return [NilClass] nil.
|
177
243
|
def wait_for_all()
|
178
244
|
LAUNCHED_PIDS.each do |pid|
|
179
245
|
Process.waitpid(pid)
|
180
246
|
end
|
247
|
+
|
248
|
+
return nil
|
181
249
|
end
|
182
250
|
|
183
251
|
|
252
|
+
# Send the TERM signal to each process launched by launch_all.
|
253
|
+
#
|
254
|
+
# @return [NilClass] nil.
|
184
255
|
def kill_all()
|
185
256
|
LAUNCHED_PIDS.each do |pid|
|
186
257
|
system "kill -15 #{pid}"
|
187
258
|
end
|
259
|
+
|
260
|
+
return nil
|
188
261
|
end
|
189
262
|
|
190
263
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bannister
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Alex Young
|
@@ -15,10 +15,23 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-10-13 00:00:00 +01:00
|
19
19
|
default_executable:
|
20
|
-
dependencies:
|
21
|
-
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: bluecloth
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
22
35
|
description: |
|
23
36
|
An application launcher which maintains a tree of processes to keep background
|
24
37
|
processes tied to the launcher.
|
@@ -33,9 +46,9 @@ extra_rdoc_files: []
|
|
33
46
|
|
34
47
|
files:
|
35
48
|
- bin/bannister
|
36
|
-
- lib/bannister/apache.rb
|
37
|
-
- lib/bannister/recurse.rb
|
38
49
|
- lib/bannister/version.rb
|
50
|
+
- lib/bannister/recurse.rb
|
51
|
+
- lib/bannister/apache.rb
|
39
52
|
- lib/bannister.rb
|
40
53
|
- README.md
|
41
54
|
- Rakefile
|