2011-12-05 18:58:23 -05:00
|
|
|
require 'optparse'
|
|
|
|
require 'puma/const'
|
2011-12-07 16:42:53 -05:00
|
|
|
require 'puma/configuration'
|
2011-12-05 18:58:23 -05:00
|
|
|
require 'yaml'
|
|
|
|
require 'uri'
|
|
|
|
require 'socket'
|
|
|
|
module Puma
|
|
|
|
class ControlCLI
|
|
|
|
|
2012-10-16 01:37:28 -04:00
|
|
|
COMMANDS = %w{halt restart start stats status stop}
|
2012-09-02 08:56:05 -04:00
|
|
|
|
|
|
|
def is_windows?
|
|
|
|
RUBY_PLATFORM =~ /(win|w)32$/ ? true : false
|
|
|
|
end
|
|
|
|
|
2012-09-25 12:40:00 -04:00
|
|
|
def initialize(argv, stdout=STDOUT, stderr=STDERR)
|
2012-10-16 01:37:28 -04:00
|
|
|
@argv = argv
|
2011-12-07 17:48:41 -05:00
|
|
|
@stdout = stdout
|
2012-09-25 12:40:00 -04:00
|
|
|
@stderr = stderr
|
2012-09-02 08:56:05 -04:00
|
|
|
@options = {}
|
|
|
|
|
2012-10-16 01:24:22 -04:00
|
|
|
opts = OptionParser.new do |o|
|
2012-10-16 01:41:23 -04:00
|
|
|
o.banner = "Usage: pumactl (-p PID | -P pidfile | -S status_file | -C url -T token) (#{COMMANDS.join("|")})"
|
2012-10-16 01:24:22 -04:00
|
|
|
|
|
|
|
o.on "-S", "--state PATH", "Where the state file to use is" do |arg|
|
2012-09-02 08:56:05 -04:00
|
|
|
@options[:status_path] = arg
|
|
|
|
end
|
2012-10-16 01:24:22 -04:00
|
|
|
|
|
|
|
o.on "-Q", "--quiet", "Not display messages" do |arg|
|
2012-09-02 08:56:05 -04:00
|
|
|
@options[:quiet_flag] = true
|
|
|
|
end
|
2012-10-16 01:24:22 -04:00
|
|
|
|
|
|
|
o.on "-P", "--pidfile PATH", "Pid file" do |arg|
|
2012-09-02 08:56:05 -04:00
|
|
|
@options[:pid_file] = arg
|
|
|
|
end
|
2012-10-16 01:24:22 -04:00
|
|
|
|
2012-10-16 01:41:23 -04:00
|
|
|
o.on "-p", "--pid PID", "Pid" do |arg|
|
|
|
|
@options[:pid] = arg.to_i
|
|
|
|
end
|
|
|
|
|
2012-10-16 01:24:22 -04:00
|
|
|
o.on "-C", "--control-url URL", "The bind url to use for the control server" do |arg|
|
2012-09-02 08:56:05 -04:00
|
|
|
@options[:control_url] = arg
|
2011-12-05 18:58:23 -05:00
|
|
|
end
|
2012-10-16 01:24:22 -04:00
|
|
|
|
|
|
|
o.on "-T", "--control-token TOKEN", "The token to use as authentication for the control server" do |arg|
|
2012-09-02 08:56:05 -04:00
|
|
|
@options[:control_auth_token] = arg
|
|
|
|
end
|
2012-10-16 01:24:22 -04:00
|
|
|
|
|
|
|
o.on_tail("-H", "--help", "Show this message") do
|
2012-10-16 01:37:28 -04:00
|
|
|
@stdout.puts o
|
2012-09-02 08:56:05 -04:00
|
|
|
exit
|
|
|
|
end
|
2012-10-16 01:24:22 -04:00
|
|
|
|
|
|
|
o.on_tail("-V", "--version", "Show version") do
|
2012-09-02 08:56:05 -04:00
|
|
|
puts Const::PUMA_VERSION
|
|
|
|
exit
|
|
|
|
end
|
2012-10-16 01:24:22 -04:00
|
|
|
end
|
|
|
|
|
2012-10-16 01:37:28 -04:00
|
|
|
opts.order!(argv) { |a| opts.terminate a }
|
2012-09-02 08:56:05 -04:00
|
|
|
|
|
|
|
command = argv.shift
|
|
|
|
@options[:command] = command if command
|
2012-10-16 01:24:22 -04:00
|
|
|
|
2012-09-02 08:56:05 -04:00
|
|
|
# check present of command
|
|
|
|
unless @options[:command]
|
|
|
|
raise "Available commands: #{COMMANDS.join(", ")}"
|
2012-10-16 01:24:22 -04:00
|
|
|
end
|
|
|
|
|
2012-09-02 08:56:05 -04:00
|
|
|
unless COMMANDS.include? @options[:command]
|
|
|
|
raise "Invalid command: #{@options[:command]}"
|
2011-12-05 18:58:23 -05:00
|
|
|
end
|
2012-10-16 01:24:22 -04:00
|
|
|
|
2012-09-02 08:56:05 -04:00
|
|
|
rescue => e
|
|
|
|
@stdout.puts e.message
|
|
|
|
exit 1
|
|
|
|
end
|
|
|
|
|
2012-10-16 01:24:22 -04:00
|
|
|
def message(msg)
|
2012-09-02 08:56:05 -04:00
|
|
|
@stdout.puts msg unless @options[:quiet_flag]
|
2011-12-05 18:58:23 -05:00
|
|
|
end
|
|
|
|
|
2012-09-02 08:56:05 -04:00
|
|
|
def prepare_configuration
|
|
|
|
if @options.has_key? :status_path
|
2012-10-16 01:24:22 -04:00
|
|
|
unless File.exist? @options[:status_path]
|
|
|
|
raise "Status file not found: #{@options[:status_path]}"
|
|
|
|
end
|
|
|
|
|
2012-09-02 08:56:05 -04:00
|
|
|
status = YAML.load File.read(@options[:status_path])
|
2012-10-16 01:24:22 -04:00
|
|
|
|
2012-09-02 08:56:05 -04:00
|
|
|
if status.has_key? "config"
|
2012-10-16 01:24:22 -04:00
|
|
|
|
|
|
|
conf = status["config"]
|
|
|
|
|
2012-09-02 08:56:05 -04:00
|
|
|
# get control_url
|
2012-10-16 01:24:22 -04:00
|
|
|
if url = conf.options[:control_url]
|
|
|
|
@options[:control_url] = url
|
2012-09-02 08:56:05 -04:00
|
|
|
end
|
2012-10-16 01:24:22 -04:00
|
|
|
|
2012-09-02 08:56:05 -04:00
|
|
|
# get control_auth_token
|
2012-10-16 01:24:22 -04:00
|
|
|
if token = conf.options[:control_auth_token]
|
|
|
|
@options[:control_auth_token] = token
|
2012-09-02 08:56:05 -04:00
|
|
|
end
|
2012-10-16 01:24:22 -04:00
|
|
|
|
2012-09-02 08:56:05 -04:00
|
|
|
# get pid
|
|
|
|
@options[:pid] = status["pid"].to_i
|
2011-12-05 18:58:23 -05:00
|
|
|
else
|
2012-09-02 08:56:05 -04:00
|
|
|
raise "Invalid status file: #{@options[:status_path]}"
|
2011-12-05 18:58:23 -05:00
|
|
|
end
|
2012-10-16 01:24:22 -04:00
|
|
|
|
2012-09-02 08:56:05 -04:00
|
|
|
elsif @options.has_key? :pid_file
|
|
|
|
# get pid from pid_file
|
|
|
|
@options[:pid] = File.open(@options[:pid_file]).gets.to_i
|
2011-12-05 18:58:23 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-09-02 08:56:05 -04:00
|
|
|
def send_request
|
|
|
|
uri = URI.parse @options[:control_url]
|
|
|
|
|
|
|
|
# create server object by scheme
|
|
|
|
@server = case uri.scheme
|
2012-10-16 01:41:23 -04:00
|
|
|
when "tcp"
|
|
|
|
TCPSocket.new uri.host, uri.port
|
|
|
|
when "unix"
|
|
|
|
UNIXSocket.new "#{uri.host}#{uri.path}"
|
|
|
|
else
|
|
|
|
raise "Invalid scheme: #{uri.scheme}"
|
|
|
|
end
|
2012-10-16 01:24:22 -04:00
|
|
|
|
|
|
|
if @options[:command] == "status"
|
|
|
|
message "Puma is started"
|
|
|
|
else
|
2012-09-02 08:56:05 -04:00
|
|
|
url = "/#{@options[:command]}"
|
2012-10-16 01:24:22 -04:00
|
|
|
|
2012-09-02 08:56:05 -04:00
|
|
|
if @options.has_key?(:control_auth_token)
|
|
|
|
url = url + "?token=#{@options[:control_auth_token]}"
|
|
|
|
end
|
2012-10-16 01:24:22 -04:00
|
|
|
|
2012-09-02 08:56:05 -04:00
|
|
|
@server << "GET #{url} HTTP/1.0\r\n\r\n"
|
2012-10-16 01:24:22 -04:00
|
|
|
|
2012-09-02 08:56:05 -04:00
|
|
|
response = @server.read.split("\r\n")
|
2012-10-16 01:24:22 -04:00
|
|
|
|
2012-09-02 08:56:05 -04:00
|
|
|
(@http,@code,@message) = response.first.split(" ")
|
2012-10-16 01:24:22 -04:00
|
|
|
|
2012-09-02 08:56:05 -04:00
|
|
|
if @code == "403"
|
|
|
|
raise "Unauthorized access to server (wrong auth token)"
|
|
|
|
elsif @code != "200"
|
|
|
|
raise "Bad response from server: #{@code}"
|
|
|
|
end
|
2012-10-16 01:24:22 -04:00
|
|
|
|
2012-09-02 08:56:05 -04:00
|
|
|
message "Command #{@options[:command]} sent success"
|
2011-12-05 18:58:23 -05:00
|
|
|
end
|
2012-09-02 08:56:05 -04:00
|
|
|
|
|
|
|
@server.close
|
2011-12-05 18:58:23 -05:00
|
|
|
end
|
|
|
|
|
2012-09-02 08:56:05 -04:00
|
|
|
def send_signal
|
2012-10-16 01:41:23 -04:00
|
|
|
unless pid = @options[:pid]
|
|
|
|
raise "Neither pid nor control url available"
|
|
|
|
end
|
|
|
|
|
|
|
|
begin
|
|
|
|
Process.getpgid pid
|
|
|
|
rescue SystemCallError
|
|
|
|
raise "No pid '#{pid}' found"
|
|
|
|
end
|
2012-10-16 01:24:22 -04:00
|
|
|
|
2012-09-02 08:56:05 -04:00
|
|
|
case @options[:command]
|
|
|
|
when "restart"
|
2012-10-16 01:41:23 -04:00
|
|
|
Process.kill "SIGUSR2", pid
|
2012-10-16 01:24:22 -04:00
|
|
|
|
2012-09-02 08:56:05 -04:00
|
|
|
when "halt"
|
2012-10-16 01:41:23 -04:00
|
|
|
Process.kill "QUIT", pid
|
2012-10-16 01:24:22 -04:00
|
|
|
|
2012-09-02 08:56:05 -04:00
|
|
|
when "stop"
|
2012-10-16 01:41:23 -04:00
|
|
|
Process.kill "SIGTERM", pid
|
|
|
|
|
|
|
|
when "stats"
|
|
|
|
puts "Stats not available via pid only"
|
|
|
|
return
|
2012-10-16 01:24:22 -04:00
|
|
|
|
2011-12-05 18:58:23 -05:00
|
|
|
else
|
2012-09-02 08:56:05 -04:00
|
|
|
message "Puma is started"
|
|
|
|
return
|
2011-12-05 18:58:23 -05:00
|
|
|
end
|
2012-10-16 01:24:22 -04:00
|
|
|
|
2012-09-02 08:56:05 -04:00
|
|
|
message "Command #{@options[:command]} sent success"
|
2011-12-05 18:58:23 -05:00
|
|
|
end
|
|
|
|
|
2012-09-02 08:56:05 -04:00
|
|
|
def run
|
2012-10-16 01:37:28 -04:00
|
|
|
if @options[:command] == "start"
|
|
|
|
require 'puma/cli'
|
|
|
|
|
|
|
|
cli = Puma::CLI.new @argv, @stdout, @stderr
|
|
|
|
cli.run
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2012-09-02 08:56:05 -04:00
|
|
|
prepare_configuration
|
|
|
|
|
|
|
|
if is_windows?
|
|
|
|
send_request
|
2011-12-05 18:58:23 -05:00
|
|
|
else
|
2012-09-02 08:56:05 -04:00
|
|
|
@options.has_key?(:control_url) ? send_request : send_signal
|
2011-12-05 18:58:23 -05:00
|
|
|
end
|
|
|
|
|
2012-09-02 08:56:05 -04:00
|
|
|
rescue => e
|
|
|
|
message e.message
|
|
|
|
exit 1
|
2011-12-05 18:58:23 -05:00
|
|
|
end
|
|
|
|
end
|
2012-09-02 08:56:05 -04:00
|
|
|
end
|