Add irs_process_scripts plugin to replace process control scripts used
authorTom Hughes <tom@compton.nu>
Mon, 15 Jun 2009 11:32:41 +0000 (11:32 +0000)
committerTom Hughes <tom@compton.nu>
Mon, 15 Jun 2009 11:32:41 +0000 (11:32 +0000)
by live site which were dropped in rails 2.3 core.

14 files changed:
script/process/inspector
script/process/reaper
script/process/spawner
vendor/plugins/irs_process_scripts/MIT-LICENSE [new file with mode: 0644]
vendor/plugins/irs_process_scripts/README [new file with mode: 0644]
vendor/plugins/irs_process_scripts/Rakefile [new file with mode: 0644]
vendor/plugins/irs_process_scripts/install.rb [new file with mode: 0644]
vendor/plugins/irs_process_scripts/lib/commands/process/inspector.rb [new file with mode: 0644]
vendor/plugins/irs_process_scripts/lib/commands/process/reaper.rb [new file with mode: 0644]
vendor/plugins/irs_process_scripts/lib/commands/process/spawner.rb [new file with mode: 0644]
vendor/plugins/irs_process_scripts/script/inspector [new file with mode: 0755]
vendor/plugins/irs_process_scripts/script/reaper [new file with mode: 0755]
vendor/plugins/irs_process_scripts/script/spawner [new file with mode: 0755]
vendor/plugins/irs_process_scripts/uninstall.rb [new file with mode: 0644]

index bf25ad86d189b6fcbf762ab5118fa40952bec2bc..35c1bae9dec2a5a37c2b0b887fa7a1a4aa4fad52 100755 (executable)
@@ -1,3 +1,4 @@
 #!/usr/bin/env ruby
 require File.dirname(__FILE__) + '/../../config/boot'
+$:.unshift "#{RAILS_ROOT}/vendor/plugins/irs_process_scripts/lib"
 require 'commands/process/inspector'
index c77f04535f97fe2b973707033dbcb48732965842..1ee7dfe1221270a9d019b038035f9ba594490ac2 100755 (executable)
@@ -1,3 +1,4 @@
 #!/usr/bin/env ruby
 require File.dirname(__FILE__) + '/../../config/boot'
+$:.unshift "#{RAILS_ROOT}/vendor/plugins/irs_process_scripts/lib"
 require 'commands/process/reaper'
index 7118f3983c75075a6b276d77e060aef68551fb57..2d27c1b81385bb910818c81ef3b0671ccf4d8e1a 100755 (executable)
@@ -1,3 +1,4 @@
 #!/usr/bin/env ruby
 require File.dirname(__FILE__) + '/../../config/boot'
+$:.unshift "#{RAILS_ROOT}/vendor/plugins/irs_process_scripts/lib"
 require 'commands/process/spawner'
diff --git a/vendor/plugins/irs_process_scripts/MIT-LICENSE b/vendor/plugins/irs_process_scripts/MIT-LICENSE
new file mode 100644 (file)
index 0000000..df66034
--- /dev/null
@@ -0,0 +1,20 @@
+Copyright (c) 2009 David Heinemeier Hansson
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/vendor/plugins/irs_process_scripts/README b/vendor/plugins/irs_process_scripts/README
new file mode 100644 (file)
index 0000000..39d3f3a
--- /dev/null
@@ -0,0 +1,11 @@
+IrsProcessScripts
+=================
+
+Contains the deprecated process control scripts from Rails 2.2 that were removed in Rails 2.3. They are:
+
+* Inspector
+* Spawner
+* Reaper
+
+
+Copyright (c) 2009 David Heinemeier Hansson, released under the MIT license
diff --git a/vendor/plugins/irs_process_scripts/Rakefile b/vendor/plugins/irs_process_scripts/Rakefile
new file mode 100644 (file)
index 0000000..aa8bd79
--- /dev/null
@@ -0,0 +1,23 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+desc 'Default: run unit tests.'
+task :default => :test
+
+desc 'Test the irs_process_scripts plugin.'
+Rake::TestTask.new(:test) do |t|
+  t.libs << 'lib'
+  t.libs << 'test'
+  t.pattern = 'test/**/*_test.rb'
+  t.verbose = true
+end
+
+desc 'Generate documentation for the irs_process_scripts plugin.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+  rdoc.rdoc_dir = 'rdoc'
+  rdoc.title    = 'IrsProcessScripts'
+  rdoc.options << '--line-numbers' << '--inline-source'
+  rdoc.rdoc_files.include('README')
+  rdoc.rdoc_files.include('lib/**/*.rb')
+end
diff --git a/vendor/plugins/irs_process_scripts/install.rb b/vendor/plugins/irs_process_scripts/install.rb
new file mode 100644 (file)
index 0000000..f922ef8
--- /dev/null
@@ -0,0 +1,9 @@
+# Install hook code here
+unless defined?(RAILS_ROOT)
+  $stderr.puts "$0 must be run from RAILS_ROOT with -rconfig/boot"
+  exit
+end
+
+require 'fileutils'
+FileUtils.rm_rf(RAILS_ROOT + '/script/process') # remove the old stubs first
+FileUtils.cp_r(RAILS_ROOT + '/vendor/plugins/irs_process_scripts/script', RAILS_ROOT + '/script/process')
diff --git a/vendor/plugins/irs_process_scripts/lib/commands/process/inspector.rb b/vendor/plugins/irs_process_scripts/lib/commands/process/inspector.rb
new file mode 100644 (file)
index 0000000..8a6437e
--- /dev/null
@@ -0,0 +1,68 @@
+require 'optparse'
+
+if RUBY_PLATFORM =~ /(:?mswin|mingw)/ then abort("Inspector is only for Unix") end
+
+OPTIONS = {
+  :pid_path => File.expand_path(RAILS_ROOT + '/tmp/pids'),
+  :pattern  => "dispatch.*.pid",
+  :ps       => "ps -o pid,state,user,start,time,pcpu,vsz,majflt,command -p %s"
+}
+
+class Inspector
+  def self.inspect(pid_path, pattern)
+    new(pid_path, pattern).inspect
+  end
+
+  def initialize(pid_path, pattern)
+    @pid_path, @pattern = pid_path, pattern
+  end
+
+  def inspect
+    header = `#{OPTIONS[:ps] % 1}`.split("\n")[0] + "\n"
+    lines  = pids.collect { |pid| `#{OPTIONS[:ps] % pid}`.split("\n")[1] }
+    
+    puts(header + lines.join("\n"))
+  end
+
+  private
+    def pids
+      pid_files.collect do |pid_file|
+        File.read(pid_file).to_i
+      end
+    end
+
+    def pid_files
+      Dir.glob(@pid_path + "/" + @pattern)
+    end
+end
+
+
+ARGV.options do |opts|
+  opts.banner = "Usage: inspector [options]"
+
+  opts.separator ""
+
+  opts.on <<-EOF
+  Description:
+    Displays system information about Rails dispatchers (or other processes that use pid files) through
+    the ps command.
+
+  Examples:
+    inspector                                             # default ps on all tmp/pids/dispatch.*.pid files
+    inspector -s 'ps -o user,start,majflt,pcpu,vsz -p %s' # custom ps, %s is where the pid is interleaved
+  EOF
+
+  opts.on("  Options:")
+
+  opts.on("-s", "--ps=command", "default: #{OPTIONS[:ps]}", String)           { |v| OPTIONS[:ps] = v }
+  opts.on("-p", "--pidpath=path", "default: #{OPTIONS[:pid_path]}", String)   { |v| OPTIONS[:pid_path] = v }
+  opts.on("-r", "--pattern=pattern", "default: #{OPTIONS[:pattern]}", String) { |v| OPTIONS[:pattern] = v }
+
+  opts.separator ""
+
+  opts.on("-h", "--help", "Show this help message.") { puts opts; exit }
+
+  opts.parse!
+end
+
+Inspector.inspect(OPTIONS[:pid_path], OPTIONS[:pattern])
diff --git a/vendor/plugins/irs_process_scripts/lib/commands/process/reaper.rb b/vendor/plugins/irs_process_scripts/lib/commands/process/reaper.rb
new file mode 100644 (file)
index 0000000..95175d4
--- /dev/null
@@ -0,0 +1,149 @@
+require 'optparse'
+require 'net/http'
+require 'uri'
+
+if RUBY_PLATFORM =~ /(:?mswin|mingw)/ then abort("Reaper is only for Unix") end
+
+class Killer
+  class << self
+    # Searches for all processes matching the given keywords, and then invokes
+    # a specific action on each of them. This is useful for (e.g.) reloading a
+    # set of processes:
+    #
+    #   Killer.process(:reload, "/tmp/pids", "dispatcher.*.pid")
+    def process(action, pid_path, pattern, keyword)
+      new(pid_path, pattern, keyword).process(action)
+    end
+
+    # Forces the (rails) application to reload by sending a +HUP+ signal to the
+    # process.
+    def reload(pid)
+      `kill -s HUP #{pid}`
+    end
+
+    # Force the (rails) application to restart by sending a +USR2+ signal to the
+    # process.
+    def restart(pid)
+      `kill -s USR2 #{pid}`
+    end
+
+    # Forces the (rails) application to gracefully terminate by sending a
+    # +TERM+ signal to the process.
+    def graceful(pid)
+      `kill -s TERM #{pid}`
+    end
+
+    # Forces the (rails) application to terminate immediately by sending a -9
+    # signal to the process.
+    def kill(pid)
+      `kill -9 #{pid}`
+    end
+
+    # Send a +USR1+ signal to the process.
+    def usr1(pid)
+      `kill -s USR1 #{pid}`
+    end
+  end
+
+  def initialize(pid_path, pattern, keyword=nil)
+    @pid_path, @pattern, @keyword = pid_path, pattern, keyword
+  end
+
+  def process(action)
+    pids = find_processes
+
+    if pids.empty?
+      warn "Couldn't find any pid file in '#{@pid_path}' matching '#{@pattern}'"
+      warn "(also looked for processes matching #{@keyword.inspect})" if @keyword
+    else
+      pids.each do |pid|
+        puts "#{action.capitalize}ing #{pid}"
+        self.class.send(action, pid)
+      end
+      
+      delete_pid_files if terminating?(action)
+    end      
+  end
+  
+  private
+    def terminating?(action)
+      [ "kill", "graceful" ].include?(action)
+    end
+  
+    def find_processes
+      files = pid_files
+      if files.empty?
+        find_processes_via_grep
+      else
+        files.collect { |pid_file| File.read(pid_file).to_i }
+      end
+    end
+
+    def find_processes_via_grep
+      lines = `ps axww -o 'pid command' | grep #{@keyword}`.split(/\n/).
+        reject { |line| line =~ /inq|ps axww|grep|spawn-fcgi|spawner|reaper/ }
+      lines.map { |line| line[/^\s*(\d+)/, 1].to_i }
+    end
+    
+    def delete_pid_files
+      pid_files.each { |pid_file| File.delete(pid_file) }
+    end
+    
+    def pid_files
+      Dir.glob(@pid_path + "/" + @pattern)
+    end
+end
+
+
+OPTIONS = {
+  :action     => "restart",
+  :pid_path   => File.expand_path(RAILS_ROOT + '/tmp/pids'),
+  :pattern    => "dispatch.[0-9]*.pid",
+  :dispatcher => File.expand_path("#{RAILS_ROOT}/public/dispatch.fcgi")
+}
+
+ARGV.options do |opts|
+  opts.banner = "Usage: reaper [options]"
+
+  opts.separator ""
+
+  opts.on <<-EOF
+  Description:
+    The reaper is used to restart, reload, gracefully exit, and forcefully exit processes
+    running a Rails Dispatcher (or any other process responding to the same signals). This
+    is commonly done when a new version of the application is available, so the existing
+    processes can be updated to use the latest code.
+
+    It uses pid files to work on the processes and by default assume them to be located
+    in RAILS_ROOT/tmp/pids. 
+
+    The reaper actions are:
+
+    * restart : Restarts the application by reloading both application and framework code
+    * reload  : Only reloads the application, but not the framework (like the development environment)
+    * graceful: Marks all of the processes for exit after the next request
+    * kill    : Forcefully exists all processes regardless of whether they're currently serving a request
+
+    Restart is the most common and default action.
+
+  Examples:
+    reaper                  # restarts the default dispatchers
+    reaper -a reload        # reload the default dispatchers
+    reaper -a kill -r *.pid # kill all processes that keep pids in tmp/pids
+  EOF
+
+  opts.on("  Options:")
+
+  opts.on("-a", "--action=name", "reload|graceful|kill (default: #{OPTIONS[:action]})", String)  { |v| OPTIONS[:action] = v }
+  opts.on("-p", "--pidpath=path", "default: #{OPTIONS[:pid_path]}", String)                      { |v| OPTIONS[:pid_path] = v }
+  opts.on("-r", "--pattern=pattern", "default: #{OPTIONS[:pattern]}", String)                    { |v| OPTIONS[:pattern] = v }
+  opts.on("-d", "--dispatcher=path", "DEPRECATED. default: #{OPTIONS[:dispatcher]}", String)     { |v| OPTIONS[:dispatcher] = v }
+
+  opts.separator ""
+
+  opts.on("-h", "--help", "Show this help message.") { puts opts; exit }
+
+  opts.parse!
+end
+
+Killer.process(OPTIONS[:action], OPTIONS[:pid_path], OPTIONS[:pattern], OPTIONS[:dispatcher])
diff --git a/vendor/plugins/irs_process_scripts/lib/commands/process/spawner.rb b/vendor/plugins/irs_process_scripts/lib/commands/process/spawner.rb
new file mode 100644 (file)
index 0000000..8bf47ab
--- /dev/null
@@ -0,0 +1,219 @@
+require 'active_support'
+require 'optparse'
+require 'socket'
+require 'fileutils'
+
+def daemonize #:nodoc:
+  exit if fork                   # Parent exits, child continues.
+  Process.setsid                 # Become session leader.
+  exit if fork                   # Zap session leader. See [1].
+  Dir.chdir "/"                  # Release old working directory.
+  File.umask 0000                # Ensure sensible umask. Adjust as needed.
+  STDIN.reopen "/dev/null"       # Free file descriptors and
+  STDOUT.reopen "/dev/null", "a" # point them somewhere sensible.
+  STDERR.reopen STDOUT           # STDOUT/ERR should better go to a logfile.
+end
+
+class Spawner
+  def self.record_pid(name = "#{OPTIONS[:process]}.spawner", id = Process.pid)
+    FileUtils.mkdir_p(OPTIONS[:pids])
+    File.open(File.expand_path(OPTIONS[:pids] + "/#{name}.pid"), "w+") { |f| f.write(id) }
+  end
+
+  def self.spawn_all
+    OPTIONS[:instances].times do |i|
+      port = OPTIONS[:port] + i
+      print "Checking if something is already running on #{OPTIONS[:address]}:#{port}..."
+
+      begin
+        srv = TCPServer.new(OPTIONS[:address], port)
+        srv.close
+        srv = nil
+
+        puts "NO"
+        puts "Starting dispatcher on port: #{OPTIONS[:address]}:#{port}"
+
+        FileUtils.mkdir_p(OPTIONS[:pids])
+        spawn(port)
+      rescue
+        puts "YES"
+      end
+    end
+  end
+end
+
+class FcgiSpawner < Spawner
+  def self.spawn(port)
+    cmd = "#{OPTIONS[:spawner]} -f #{OPTIONS[:dispatcher]} -p #{port} -P #{OPTIONS[:pids]}/#{OPTIONS[:process]}.#{port}.pid"
+    cmd << " -a #{OPTIONS[:address]}" if can_bind_to_custom_address?
+    system(cmd)
+  end
+
+  def self.can_bind_to_custom_address?
+    @@can_bind_to_custom_address ||= /^\s-a\s/.match `#{OPTIONS[:spawner]} -h`
+  end
+end
+
+class MongrelSpawner < Spawner
+  def self.spawn(port)
+    cmd =
+      "mongrel_rails start -d " +
+      "-a #{OPTIONS[:address]} " +
+      "-p #{port} " +
+      "-P #{OPTIONS[:pids]}/#{OPTIONS[:process]}.#{port}.pid " +
+      "-e #{OPTIONS[:environment]} " +
+      "-c #{OPTIONS[:rails_root]} " +
+      "-l #{OPTIONS[:rails_root]}/log/mongrel.log"
+
+    # Add prefix functionality to spawner's call to mongrel_rails
+    # Digging through mongrel's project subversion server, the earliest
+    # Tag that has prefix implemented in the bin/mongrel_rails file
+    # is 0.3.15 which also happens to be the earliest tag listed.
+    # References: http://mongrel.rubyforge.org/svn/tags
+    if Mongrel::Const::MONGREL_VERSION.to_f >=0.3 && !OPTIONS[:prefix].nil?
+      cmd = cmd + " --prefix #{OPTIONS[:prefix]}"
+    end
+    system(cmd)
+  end
+  
+  def self.can_bind_to_custom_address?
+    true
+  end
+end
+
+
+begin
+  require_library_or_gem 'fcgi'
+rescue Exception
+  # FCGI not available
+end
+
+begin
+  require_library_or_gem 'mongrel'
+rescue Exception
+  # Mongrel not available
+end
+
+server = case ARGV.first
+  when "fcgi", "mongrel"
+    ARGV.shift
+  else
+    if defined?(Mongrel)
+      "mongrel"
+    elsif RUBY_PLATFORM !~ /(:?mswin|mingw)/ && !silence_stderr { `spawn-fcgi -version` }.blank? && defined?(FCGI)
+      "fcgi"
+    end
+end
+
+case server
+  when "fcgi"
+    puts "=> Starting FCGI dispatchers"
+    spawner_class = FcgiSpawner
+  when "mongrel"
+    puts "=> Starting mongrel dispatchers"
+    spawner_class = MongrelSpawner
+  else
+    puts "Neither FCGI (spawn-fcgi) nor Mongrel was installed and available!"
+    exit(0)
+end
+
+
+
+OPTIONS = {
+  :environment => "production",
+  :spawner     => '/usr/bin/env spawn-fcgi',
+  :dispatcher  => File.expand_path(RELATIVE_RAILS_ROOT + '/public/dispatch.fcgi'),
+  :pids        => File.expand_path(RELATIVE_RAILS_ROOT + "/tmp/pids"),
+  :rails_root  => File.expand_path(RELATIVE_RAILS_ROOT),
+  :process     => "dispatch",
+  :port        => 8000,
+  :address     => '0.0.0.0',
+  :instances   => 3,
+  :repeat      => nil,
+  :prefix      => nil
+}
+
+ARGV.options do |opts|
+  opts.banner = "Usage: spawner [platform] [options]"
+
+  opts.separator ""
+
+  opts.on <<-EOF
+  Description:
+    The spawner is a wrapper for spawn-fcgi and mongrel that makes it
+    easier to start multiple processes running the Rails dispatcher. The
+    spawn-fcgi command is included with the lighttpd web server, but can
+    be used with both Apache and lighttpd (and any other web server
+    supporting externally managed FCGI processes). Mongrel automatically
+    ships with with mongrel_rails for starting dispatchers.
+
+    The first choice you need to make is whether to spawn the Rails
+    dispatchers as FCGI or Mongrel. By default, this spawner will prefer
+    Mongrel, so if that's installed, and no platform choice is made,
+    Mongrel is used.
+
+    Then decide a starting port (default is 8000) and the number of FCGI
+    process instances you'd like to run. So if you pick 9100 and 3
+    instances, you'll start processes on 9100, 9101, and 9102.
+
+    By setting the repeat option, you get a protection loop, which will
+    attempt to restart any FCGI processes that might have been exited or
+    outright crashed.
+
+    You can select bind address for started processes. By default these
+    listen on every interface. For single machine installations you would
+    probably want to use 127.0.0.1, hiding them form the outside world.
+
+     Examples:
+       spawner               # starts instances on 8000, 8001, and 8002
+                             # using Mongrel if available.
+       spawner fcgi          # starts instances on 8000, 8001, and 8002
+                             # using FCGI.
+       spawner mongrel -i 5  # starts instances on 8000, 8001, 8002,
+                             # 8003, and 8004 using Mongrel.
+       spawner -p 9100 -i 10 # starts 10 instances counting from 9100 to
+                             # 9109 using Mongrel if available.
+       spawner -p 9100 -r 5  # starts 3 instances counting from 9100 to
+                             # 9102 and attempts start them every 5
+                             # seconds.
+       spawner -a 127.0.0.1  # starts 3 instances binding to localhost
+  EOF
+
+  opts.on("  Options:")
+
+  opts.on("-p", "--port=number",      Integer, "Starting port number (default: #{OPTIONS[:port]})")                { |v| OPTIONS[:port] = v }
+
+  if spawner_class.can_bind_to_custom_address?
+    opts.on("-a", "--address=ip",     String,  "Bind to IP address (default: #{OPTIONS[:address]})")                { |v| OPTIONS[:address] = v }
+  end
+
+  opts.on("-p", "--port=number",      Integer, "Starting port number (default: #{OPTIONS[:port]})")                { |v| OPTIONS[:port] = v }
+  opts.on("-i", "--instances=number", Integer, "Number of instances (default: #{OPTIONS[:instances]})")            { |v| OPTIONS[:instances] = v }
+  opts.on("-r", "--repeat=seconds",   Integer, "Repeat spawn attempts every n seconds (default: off)")             { |v| OPTIONS[:repeat] = v }
+  opts.on("-e", "--environment=name", String,  "test|development|production (default: #{OPTIONS[:environment]})")  { |v| OPTIONS[:environment] = v }
+  opts.on("-P", "--prefix=path",      String,  "URL prefix for Rails app. [Used only with Mongrel > v0.3.15]: (default: #{OPTIONS[:prefix]})")         { |v| OPTIONS[:prefix] = v }
+  opts.on("-n", "--process=name",     String,  "default: #{OPTIONS[:process]}")                                    { |v| OPTIONS[:process] = v }
+  opts.on("-s", "--spawner=path",     String,  "default: #{OPTIONS[:spawner]}")                                    { |v| OPTIONS[:spawner] = v }
+  opts.on("-d", "--dispatcher=path",  String,  "default: #{OPTIONS[:dispatcher]}") { |dispatcher| OPTIONS[:dispatcher] = File.expand_path(dispatcher) }
+
+  opts.separator ""
+
+  opts.on("-h", "--help", "Show this help message.") { puts opts; exit }
+
+  opts.parse!
+end
+
+ENV["RAILS_ENV"] = OPTIONS[:environment]
+
+if OPTIONS[:repeat]
+  daemonize
+  trap("TERM") { exit }
+  spawner_class.record_pid
+
+  loop do
+    spawner_class.spawn_all
+    sleep(OPTIONS[:repeat])
+  end
+else
+  spawner_class.spawn_all
+end
diff --git a/vendor/plugins/irs_process_scripts/script/inspector b/vendor/plugins/irs_process_scripts/script/inspector
new file mode 100755 (executable)
index 0000000..35c1bae
--- /dev/null
@@ -0,0 +1,4 @@
+#!/usr/bin/env ruby
+require File.dirname(__FILE__) + '/../../config/boot'
+$:.unshift "#{RAILS_ROOT}/vendor/plugins/irs_process_scripts/lib"
+require 'commands/process/inspector'
diff --git a/vendor/plugins/irs_process_scripts/script/reaper b/vendor/plugins/irs_process_scripts/script/reaper
new file mode 100755 (executable)
index 0000000..1ee7dfe
--- /dev/null
@@ -0,0 +1,4 @@
+#!/usr/bin/env ruby
+require File.dirname(__FILE__) + '/../../config/boot'
+$:.unshift "#{RAILS_ROOT}/vendor/plugins/irs_process_scripts/lib"
+require 'commands/process/reaper'
diff --git a/vendor/plugins/irs_process_scripts/script/spawner b/vendor/plugins/irs_process_scripts/script/spawner
new file mode 100755 (executable)
index 0000000..2d27c1b
--- /dev/null
@@ -0,0 +1,4 @@
+#!/usr/bin/env ruby
+require File.dirname(__FILE__) + '/../../config/boot'
+$:.unshift "#{RAILS_ROOT}/vendor/plugins/irs_process_scripts/lib"
+require 'commands/process/spawner'
diff --git a/vendor/plugins/irs_process_scripts/uninstall.rb b/vendor/plugins/irs_process_scripts/uninstall.rb
new file mode 100644 (file)
index 0000000..97196a9
--- /dev/null
@@ -0,0 +1,8 @@
+# Install hook code here
+unless defined?(RAILS_ROOT)
+  $stderr.puts "$0 must be run from RAILS_ROOT with -rconfig/boot"
+  exit
+end
+
+require 'fileutils'
+FileUtils.rm_rf(RAILS_ROOT + '/script/process')
\ No newline at end of file