mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
d75481c580
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@1909 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
123 lines
No EOL
3.8 KiB
Ruby
Executable file
123 lines
No EOL
3.8 KiB
Ruby
Executable file
#!/usr/local/bin/ruby
|
|
|
|
require 'optparse'
|
|
require 'net/http'
|
|
require 'uri'
|
|
|
|
def nudge(url, iterations)
|
|
print "Nudging #{url}: "
|
|
iterations.times { Net::HTTP.get_response(URI.parse(url)); print "."; STDOUT.flush }
|
|
puts
|
|
end
|
|
|
|
if RUBY_PLATFORM =~ /mswin32/ then abort("Reaper is only for Unix") end
|
|
|
|
class ProgramProcess
|
|
class << self
|
|
def process_keywords(action, *keywords)
|
|
processes = keywords.collect { |keyword| find_by_keyword(keyword) }.flatten
|
|
|
|
if processes.empty?
|
|
puts "Couldn't find any process matching: #{keywords.join(" or ")}"
|
|
else
|
|
processes.each do |process|
|
|
puts "#{action.capitalize}ing #{process}"
|
|
process.send(action)
|
|
end
|
|
end
|
|
end
|
|
|
|
def find_by_keyword(keyword)
|
|
process_lines_with_keyword(keyword).split("\n").collect { |line|
|
|
next if line.include?("inq") || line.include?("ps -ax") || line.include?("grep")
|
|
pid, *command = line.split
|
|
new(pid, command.join(" "))
|
|
}.compact
|
|
end
|
|
|
|
private
|
|
def process_lines_with_keyword(keyword)
|
|
`ps -ax -o 'pid command' | grep #{keyword}`
|
|
end
|
|
end
|
|
|
|
def initialize(pid, command)
|
|
@pid, @command = pid, command
|
|
end
|
|
|
|
def find
|
|
end
|
|
|
|
def reload
|
|
`kill -s HUP #{@pid}`
|
|
end
|
|
|
|
def graceful
|
|
`kill -s TERM #{@pid}`
|
|
end
|
|
|
|
def kill
|
|
`kill -9 #{@pid}`
|
|
end
|
|
|
|
def to_s
|
|
"[#{@pid}] #{@command}"
|
|
end
|
|
end
|
|
|
|
OPTIONS = {
|
|
:action => "graceful",
|
|
:dispatcher => File.expand_path(File.dirname(__FILE__) + '/../../public/dispatch.fcgi'),
|
|
:iterations => 10,
|
|
:nudge => false
|
|
}
|
|
|
|
ARGV.options do |opts|
|
|
opts.banner = "Usage: reaper [options]"
|
|
|
|
opts.separator ""
|
|
|
|
opts.on <<-EOF
|
|
Description:
|
|
The reaper is used to reload, gracefully exit, and forcefully exit FCGI processes
|
|
running a Rails Dispatcher. 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.
|
|
|
|
The reaper actions are:
|
|
|
|
* 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
|
|
|
|
Graceful exist is the most common and default action. But since the processes won't exist until after
|
|
their next request, it's often necessary to ensure that such a request occurs right after they've been
|
|
marked. That's what nudging is for.
|
|
|
|
A nudge is simply a request to a URL where the dispatcher is serving. You should perform one nudge per
|
|
FCGI process you have running if they're setup in a round-robin. Be sure to do one nudge per FCGI process
|
|
across all your servers. So three servers with 10 processes each should nudge 30 times to be sure all processes
|
|
are restarted.
|
|
|
|
NOTE: You're responsible for restarting the processes after they exit. This can be automated by using
|
|
the spinner.
|
|
Examples:
|
|
reaper -a reload
|
|
reaper -n http://www.example.com -i 10 # gracefully exit, nudge 10 times
|
|
EOF
|
|
|
|
opts.on(" Options:")
|
|
|
|
opts.on("-a", "--action=name", "reload|graceful|kill (default: #{OPTIONS[:action]})", String) { |OPTIONS[:action]| }
|
|
opts.on("-d", "--dispatcher=path", "default: #{OPTIONS[:dispatcher]}", String) { |OPTIONS[:dispatcher]| }
|
|
opts.on("-n", "--nudge=url", "Should point to URL that's handled by the FCGI process", String) { |OPTIONS[:nudge]| }
|
|
opts.on("-i", "--iterations=number", "One nudge per FCGI process running (default: #{OPTIONS[:iterations]})", Integer) { |OPTIONS[:iterations]| }
|
|
|
|
opts.separator ""
|
|
|
|
opts.on("-h", "--help", "Show this help message.") { puts opts; exit }
|
|
|
|
opts.parse!
|
|
end
|
|
|
|
ProgramProcess.process_keywords(OPTIONS[:action], OPTIONS[:dispatcher])
|
|
nudge(OPTIONS[:nudge], OPTIONS[:iterations]) if OPTIONS[:nudge] |