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 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
@@ -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
- raise "Apache2 failed to stop!"
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)
@@ -1,6 +1,6 @@
1
1
  module Bannister
2
2
 
3
- # Use the Recurse class to launch other bannister apps from this one.
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 "bannister stop" and exit.
13
+
14
+ # Run "runner stop" and exit.
15
15
  def stop
16
- system "bannister stop"
16
+ system "./runner stop"
17
17
  exit(0)
18
18
  end
19
19
 
20
20
 
21
- # If foreground is true, exec "bannister run" in @dir. Otherwise set up
22
- # traps for the right signals to a backgrounded "bannister start" process.
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
- exec "bannister run"
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
- system "bannister start &"
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
@@ -1,3 +1,3 @@
1
1
  module Bannister
2
- VERSION="0.0.1"
2
+ VERSION="0.0.2"
3
3
  end
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: 29
4
+ hash: 27
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 1
10
- version: 0.0.1
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-09-22 00:00:00 +01:00
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