rv 2.991 → 3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/CHANGELOG +1 -1
  2. data/README +8 -5
  3. data/lib/rv.rb +55 -19
  4. metadata +2 -2
data/CHANGELOG CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- v2.991. Gem'd; RDoc documentation; automated setup scripts; cluster support. Incompatible changes. Pre-release.
2
+ v3. Gem'd; RDoc documentation; automated setup scripts; cluster support; accurate status reporting. Incompatible changes
3
3
 
4
4
  v2. Mongrel static directory handler.
5
5
 
data/README CHANGED
@@ -1,7 +1,7 @@
1
1
 
2
2
  Rv
3
3
 
4
- A little <tt>init.d</tt> system for running Camping apps.
4
+ A little <tt>init.d</tt> system for running Camping apps, for Linux.
5
5
 
6
6
  == License
7
7
 
@@ -12,8 +12,11 @@ Copyright 2007 Cloudburst, LLC. See the included LICENSE file.
12
12
  * cluster support
13
13
  * custom database configuration
14
14
  * interactive setup tasks
15
+ * logging
15
16
 
16
- Linux is required. Ubuntu is known to work; Gentoo should work; others should work with minor or no changes.
17
+ Linux is required. Ubuntu and Gentoo are known to work.
18
+
19
+ Rv is designed for Camping, but it can actually manage any app for which you write a compatible Mongrel harness.
17
20
 
18
21
  = Usage
19
22
 
@@ -46,10 +49,10 @@ The script also responds to <tt>status</tt>, <tt>restart</tt>, and <tt>stop</tt>
46
49
 
47
50
  == Troubleshooting
48
51
 
49
- If you're having problems, run:
50
- RV_DEBUG=true sudo /etc/init.d/rv start
52
+ If you're having problems, first check <tt>/var/log/rv.log</tt>. If that doesn't help, run:
53
+ sudo env RV_DEBUG=true /etc/init.d/rv start
51
54
 
52
- Copy out the inner command (between the '<tt>nohup su -c "</tt>' and the first '<tt>< /dev/null...</tt>') and try running it by hand. Make sure you're using the correct user. You can also check <tt>/var/log/rv.log</tt> as well as the application log.
55
+ Copy out the inner command (between the '<tt>nohup sudo -u httpd</tt>' and the '<tt>< /dev/null</tt>') and try running it by hand. Make sure you're using the correct user.
53
56
 
54
57
  == Apache configuration
55
58
 
data/lib/rv.rb CHANGED
@@ -11,7 +11,8 @@ Available keys are:
11
11
  * <tt>'user'</tt> - the system user used to start the apps.
12
12
  * <tt>'max_tries'</tt> - the number of retries before giving up on an app (each try takes a half second).
13
13
  * <tt>'log'</tt> - the path to Rv's own logfile.
14
- * <tt>'ruby'</tt> - a string used to start the Ruby interpreter.
14
+ * <tt>'env'</tt> - the path to the <tt>env</tt> utility.
15
+ * <tt>'ruby'</tt> - the name of the Ruby interpreter.
15
16
 
16
17
  =end
17
18
 
@@ -47,7 +48,8 @@ class Rv
47
48
 
48
49
  DEFAULTS = {
49
50
  'user' => 'httpd',
50
- 'ruby' => '/usr/bin/env ruby',
51
+ 'env' => '/usr/bin/env',
52
+ 'ruby' => 'ruby',
51
53
  'conf_dir' => '/etc/rv',
52
54
  'log' => '/var/log/rv.log',
53
55
  'harness' => 'rv_harness.rb',
@@ -78,7 +80,6 @@ class Rv
78
80
  end
79
81
  system "chown #{options['user']} #{options['log']} #{options['null_stream']}"
80
82
  system "chgrp #{options['user']} #{options['log']} #{options['null_stream']}"
81
-
82
83
  end
83
84
 
84
85
  # Perform any action in VALID_ACTIONS. Defaults to running against all applications. Pass a specific app name as <tt>match</tt> if this is not what you want.
@@ -89,6 +90,7 @@ class Rv
89
90
  case action
90
91
  when "restart"
91
92
  daemon("stop", match)
93
+ sleep(5) # wait for the sockets to get released
92
94
  daemon("start", match)
93
95
  when "install"
94
96
  install
@@ -105,9 +107,12 @@ class Rv
105
107
  # Runs a daemon action. Only called from <tt>perform</tt>.
106
108
  def daemon(action, match)
107
109
  filenames = Dir["#{options['conf_dir']}/#{match}.yml"]
110
+
111
+ # sanity checks
108
112
  exit_with("No applications found for '#{match}' in #{options['conf_dir']}/") if filenames.empty?
113
+ exit_with("Can't write to the log (#{options['log']})") unless check_log
109
114
 
110
- # Examine matching applications
115
+ # examine matching applications
111
116
  filenames.each do |filename|
112
117
 
113
118
  real_config = YAML.load_file(filename)
@@ -121,12 +126,11 @@ class Rv
121
126
  @port = config['port'] += cluster_index
122
127
 
123
128
  pid_file = Rv.pid_file(config['app'], config['port'])
124
- pid = File.open(pid_file).readlines.first.chomp rescue nil
125
- running = pid ? `ps -p #{pid}`.split("\n")[1] : nil
129
+ pid = get_pid(pid_file)
126
130
 
127
131
  case action
128
132
  when "status"
129
- if running
133
+ if check_pid(pid)
130
134
  note "running"
131
135
  elsif pid
132
136
  note "has died"
@@ -134,28 +138,38 @@ class Rv
134
138
  note "not running"
135
139
  end
136
140
  when "stop"
137
- if pid and running
138
- system %[nohup su -c "kill -9 #{pid} #{options['null_stream']}" #{options['user']} #{options['log_stream']}]
139
- running = nil
140
- note "stopped"
141
+ if pid and check_pid(pid)
142
+ # send a hard kill
143
+ run "kill -9 #{pid}"
144
+ # remove the pid file, since we didn't let mongrel to do it
145
+ sleep(0.5)
146
+ unless check_pid(pid)
147
+ File.delete(pid_file)
148
+ running = nil
149
+ note "stopped"
150
+ else
151
+ note "failed to stop"
152
+ end
141
153
  elsif pid
142
- note "not running"
143
- File.delete pid_file
154
+ note "has already died"
155
+ File.delete pid_file
144
156
  else
145
- note "pid file #{pid_file.inspect} not found. Application was probably not running."
157
+ note "not running"
146
158
  end
147
159
  when "start"
148
- unless running
160
+ unless check_pid(pid)
161
+ # Gentoo requires the env variables to be set within the command, not before the sudo
149
162
  env_variables = config.map {|key, value| "RV_#{key.upcase}=#{value}"}.join(" ")
150
- system %[nohup su -c "#{env_variables} #{options['ruby']} #{options['harness']} #{options['null_stream']}" #{options['user']} #{options['log_stream']} &]
151
-
163
+ run "#{options['env']} #{env_variables} #{options['ruby']} #{options['harness']}", true
152
164
  # wait for the app to initialize
153
165
  tries = 0
154
166
  begin
155
167
  sleep(0.5)
156
168
  tries += 1
157
- end while tries < options['max_tries'] and !File.exist?(pid_file)
158
- if File.exist?(pid_file)
169
+ pid = get_pid(pid_file) # reset the pid
170
+ end while tries < options['max_tries'] and !(File.exist?(pid_file) and check_pid(pid))
171
+
172
+ if File.exist?(pid_file) and check_pid(pid)
159
173
  note "started"
160
174
  else
161
175
  note "failed to start"
@@ -255,11 +269,33 @@ class Rv
255
269
  puts msg
256
270
  exit
257
271
  end
272
+
273
+ # Makes sure the log is writeable.
274
+ def check_log
275
+ run "touch #{options['log']}"
276
+ end
277
+
278
+ # Reads a pid number from a pid_file.
279
+ def get_pid(pid_file)
280
+ File.open(pid_file).readlines.first.chomp rescue nil
281
+ end
258
282
 
283
+ # Checks if the process number <tt>pid</tt> is running.
284
+ def check_pid(pid = nil)
285
+ if pid
286
+ `ps -p #{pid}`.split("\n")[1]
287
+ end
288
+ end
289
+
259
290
  # Prints a message along with the current port.
260
291
  def note(msg)
261
292
  puts " #{msg.capitalize} (#{@port})"
262
293
  end
294
+
295
+ # Runs a command as the app user, with log redirects, in a way that doubly detaches from the terminal and doesn't require a shell.
296
+ def run(cmd, background = false)
297
+ system %[nohup sudo -u #{options['user']} #{cmd} #{options['log_stream']} #{'&' if background}]
298
+ end
263
299
 
264
300
  # system() with debugging output
265
301
  def system(string)
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: rv
5
5
  version: !ruby/object:Gem::Version
6
- version: "2.991"
7
- date: 2007-08-07 00:00:00 -04:00
6
+ version: "3"
7
+ date: 2007-08-08 00:00:00 -04:00
8
8
  summary: A little init.d system for running Camping apps.
9
9
  require_paths:
10
10
  - lib