bannister 0.0.1 → 0.0.2

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/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