class Puma::CLI

Handles invoke a Puma::Server in a command line style.

Public Class Methods

new(argv, stdout=STDOUT, stderr=STDERR) click to toggle source

Create a new CLI object using argv as the command line arguments.

stdout and stderr can be set to IO-like objects which this object will report status on.

# File lib/puma/cli.rb, line 22
def initialize(argv, stdout=STDOUT, stderr=STDERR)
  @argv = argv
  @stdout = stdout
  @stderr = stderr

  @events = Events.new @stdout, @stderr

  @server = nil
  @status = nil

  @restart = false

  @listeners = []

  setup_options

  generate_restart_data

  @inherited_fds = {}
  remove = []

  ENV.each do |k,v|
    if k =~ /PUMA_INHERIT_\d+/
      fd, url = v.split(":", 2)
      @inherited_fds[url] = fd.to_i
      remove << k
    end
  end

  remove.each do |k|
    ENV.delete k
  end
end

Public Instance Methods

delete_pidfile() click to toggle source
# File lib/puma/cli.rb, line 248
def delete_pidfile
  if path = @options[:pidfile]
    File.unlink path
  end
end
error(str) click to toggle source

Delegate error to +@events+

# File lib/puma/cli.rb, line 139
def error(str)
  @events.error str
end
generate_restart_data() click to toggle source
# File lib/puma/cli.rb, line 60
def generate_restart_data
  # Use the same trick as unicorn, namely favor PWD because
  # it will contain an unresolved symlink, useful for when
  # the pwd is /data/releases/current.
  if dir = ENV['PWD']
    s_env = File.stat(dir)
    s_pwd = File.stat(Dir.pwd)

    if s_env.ino == s_pwd.ino and s_env.dev == s_pwd.dev
      @restart_dir = dir
    end
  end

  @restart_dir ||= Dir.pwd

  @original_argv = ARGV.dup

  if defined? Rubinius::OS_ARGV
    @restart_argv = Rubinius::OS_ARGV
  else
    require 'rubygems'

    # if $0 is a file in the current directory, then restart
    # it the same, otherwise add -S on there because it was
    # picked up in PATH.
    #
    if File.exists?($0)
      arg0 = [Gem.ruby, $0]
    else
      arg0 = [Gem.ruby, "-S", $0]
    end

    @restart_argv = arg0 + ARGV
  end
end
log(str) click to toggle source

Delegate log to +@events+

# File lib/puma/cli.rb, line 133
def log(str)
  @events.log str
end
restart!() click to toggle source
# File lib/puma/cli.rb, line 96
def restart!
  @options[:on_restart].each do |blk|
    blk.call self
  end

  if IS_JRUBY
    @listeners.each_with_index do |(str,io),i|
      io.close

      # We have to unlink a unix socket path that's not being used
      uri = URI.parse str
      if uri.scheme == "unix"
        path = "#{uri.host}#{uri.path}"
        File.unlink path
      end
    end

    require 'puma/jruby_restart'
    JRubyRestart.chdir_exec(@restart_dir, Gem.ruby, *@restart_argv)
  else
    @listeners.each_with_index do |(l,io),i|
      ENV["PUMA_INHERIT_#{i}"] = "#{io.to_i}:#{l}"
    end

    if cmd = @options[:restart_cmd]
      argv = cmd.split(' ') + @original_argv
    else
      argv = @restart_argv
    end

    Dir.chdir @restart_dir
    Kernel.exec(*argv)
  end
end
restart_on_stop!() click to toggle source
# File lib/puma/cli.rb, line 56
def restart_on_stop!
  @restart = true
end
set_rack_environment() click to toggle source
# File lib/puma/cli.rb, line 239
def set_rack_environment 
  # Try the user option first, then the environment variable,
  # finally default to development

  ENV['RACK_ENV'] = @options[:environment] ||
                    ENV['RACK_ENV'] ||
                    'development'
end
setup_options() click to toggle source

Build the OptionParser object to handle the available options.

# File lib/puma/cli.rb, line 145
def setup_options
  @options = {
    :min_threads => 0,
    :max_threads => 16,
    :quiet => false,
    :binds => []
  }

  @parser = OptionParser.new do |o|
    o.on "-b", "--bind URI", "URI to bind to (tcp:// and unix:// only)" do |arg|
      @options[:binds] << arg
    end

    o.on "-C", "--config PATH", "Load PATH as a config file" do |arg|
      @options[:config_file] = arg
    end

    o.on "-I", "--include PATH", "Specify $LOAD_PATH directories" do |arg|
      $LOAD_PATH.unshift(*arg.split(':'))
    end

    o.on "-p", "--port PORT", "Define what port TCP port to bind to",
                              "Use -b for more advanced options" do |arg|
      @options[:binds] << "tcp://#{Configuration::DefaultTCPHost}:#{arg}"
    end

    o.on "--pidfile PATH", "Use PATH as a pidfile" do |arg|
      @options[:pidfile] = arg
    end

    o.on "-q", "--quiet", "Quiet down the output" do
      @options[:quiet] = true
    end

    o.on "-S", "--state PATH", "Where to store the state details" do |arg|
      @options[:state] = arg
    end

    o.on "--control URL", "The bind url to use for the control server",
                          "Use 'auto' to use temp unix server" do |arg|
      if arg
        @options[:control_url] = arg
      elsif IS_JRUBY
        raise NotImplementedError, "No default url available on JRuby"
      end
    end

    o.on "--control-token TOKEN",
         "The token to use as authentication for the control server" do |arg|
      @options[:control_auth_token] = arg
    end

    o.on '-t', '--threads INT', "min:max threads to use (default 0:16)" do |arg|
      min, max = arg.split(":")
      if max
        @options[:min_threads] = min.to_i
        @options[:max_threads] = max.to_i
      else
        @options[:min_threads] = 0
        @options[:max_threads] = arg.to_i
      end
    end

    o.on "--restart-cmd CMD",
         "The puma command to run during a hot restart",
         "Default: inferred" do |cmd|
      @options[:restart_cmd] = cmd
    end

    o.on "-e", "--environment ENVIRONMENT",
         "The environment to run the Rack app on (default development)" do |arg|
      @options[:environment] = arg
    end
  end

  @parser.banner = "puma <options> <rackup file>"

  @parser.on_tail "-h", "--help", "Show help" do
    log @parser
    exit 1
  end
end
write_pid() click to toggle source

If configured, write the pid of the current process out to a file.

# File lib/puma/cli.rb, line 231
def write_pid
  if path = @options[:pidfile]
    File.open(path, "w") do |f|
      f.puts Process.pid
    end
  end
end
write_state() click to toggle source
# File lib/puma/cli.rb, line 254
def write_state
  require 'yaml'

  if path = @options[:state]
    state = { "pid" => Process.pid }

    cfg = @config.dup
    cfg.options.delete :on_restart

    state["config"] = cfg

    File.open(path, "w") do |f|
      f.write state.to_yaml
    end
  end
end