root/trunk/vendor/rails/railties/lib/commands/process/reaper.rb @ 58

Revision 58, 3.9 KB (checked in by dema, 7 years ago)

Updating to Rails 1.1.2

Line 
1require 'optparse'
2require 'net/http'
3require 'uri'
4
5if RUBY_PLATFORM =~ /mswin32/ then abort("Reaper is only for Unix") end
6
7# Instances of this class represent a single running process. Processes may
8# be queried by "keyword" to find those that meet a specific set of criteria.
9class ProgramProcess
10  class << self
11   
12    # Searches for all processes matching the given keywords, and then invokes
13    # a specific action on each of them. This is useful for (e.g.) reloading a
14    # set of processes:
15    #
16    #   ProgramProcess.process_keywords(:reload, "basecamp")
17    def process_keywords(action, *keywords)
18      processes = keywords.collect { |keyword| find_by_keyword(keyword) }.flatten
19
20      if processes.empty?
21        puts "Couldn't find any process matching: #{keywords.join(" or ")}"
22      else
23        processes.each do |process|
24          puts "#{action.capitalize}ing #{process}"
25          process.send(action)
26        end
27      end     
28    end
29
30    # Searches for all processes matching the given keyword:
31    #
32    #   ProgramProcess.find_by_keyword("basecamp")
33    def find_by_keyword(keyword)
34      process_lines_with_keyword(keyword).split("\n").collect { |line|
35        next if line =~ /inq|ps axww|grep|spawn-fcgi|spawner|reaper/
36        pid, *command = line.split
37        new(pid, command.join(" "))
38      }.compact
39    end
40
41    private
42      def process_lines_with_keyword(keyword)
43        `ps axww -o 'pid command' | grep #{keyword}`
44      end
45  end
46
47  # Create a new ProgramProcess instance that represents the process with the
48  # given pid, running the given command.
49  def initialize(pid, command)
50    @pid, @command = pid, command
51  end
52
53  # Forces the (rails) application to reload by sending a +HUP+ signal to the
54  # process.
55  def reload
56    `kill -s HUP #{@pid}`
57  end
58
59  # Forces the (rails) application to gracefully terminate by sending a
60  # +TERM+ signal to the process.
61  def graceful
62    `kill -s TERM #{@pid}`
63  end
64
65  # Forces the (rails) application to terminate immediately by sending a -9
66  # signal to the process.
67  def kill
68    `kill -9 #{@pid}`
69  end
70
71  # Send a +USR1+ signal to the process.
72  def usr1
73    `kill -s USR1 #{@pid}`
74  end
75
76  # Force the (rails) application to restart by sending a +USR2+ signal to the
77  # process.
78  def restart
79    `kill -s USR2 #{@pid}`
80  end
81
82  def to_s #:nodoc:
83    "[#{@pid}] #{@command}"
84  end
85end
86
87OPTIONS = {
88  :action      => "restart",
89  :dispatcher  => File.expand_path(RAILS_ROOT + '/public/dispatch.fcgi')
90}
91
92ARGV.options do |opts|
93  opts.banner = "Usage: reaper [options]"
94
95  opts.separator ""
96
97  opts.on <<-EOF
98  Description:
99    The reaper is used to restart, reload, gracefully exit, and forcefully exit FCGI processes
100    running a Rails Dispatcher. This is commonly done when a new version of the application
101    is available, so the existing processes can be updated to use the latest code.
102
103    The reaper actions are:
104
105    * restart : Restarts the application by reloading both application and framework code
106    * reload  : Only reloads the application, but not the framework (like the development environment)
107    * graceful: Marks all of the processes for exit after the next request
108    * kill    : Forcefully exists all processes regardless of whether they're currently serving a request
109
110    Restart is the most common and default action.
111
112  Examples:
113    reaper # restarts the default dispatcher
114    reaper -a reload
115    reaper -a exit -d /my/special/dispatcher.fcgi
116  EOF
117
118  opts.on("  Options:")
119
120  opts.on("-a", "--action=name", "reload|graceful|kill (default: #{OPTIONS[:action]})", String)  { |OPTIONS[:action]| }
121  opts.on("-d", "--dispatcher=path", "default: #{OPTIONS[:dispatcher]}", String)                 { |OPTIONS[:dispatcher]| }
122
123  opts.separator ""
124
125  opts.on("-h", "--help", "Show this help message.") { puts opts; exit }
126
127  opts.parse!
128end
129
130ProgramProcess.process_keywords(OPTIONS[:action], OPTIONS[:dispatcher])
Note: See TracBrowser for help on using the browser.