Class: Thin::Runner
- Inherits:
-
Object
- Object
- Thin::Runner
- Defined in:
- lib/thin/runner.rb
Overview
CLI runner. Parse options and send command to the correct Controller.
Constant Summary collapse
- COMMANDS =
%w(start stop restart config)
- LINUX_ONLY_COMMANDS =
%w(install)
- CONFIGLESS_COMMANDS =
Commands that wont load options from the config file
%w(config install)
Instance Attribute Summary collapse
-
#arguments ⇒ Object
Arguments to be passed to the command.
-
#command ⇒ Object
Name of the command to be runned.
-
#options ⇒ Object
Parsed options.
Class Method Summary collapse
-
.commands ⇒ Object
Return all available commands.
Instance Method Summary collapse
-
#cluster? ⇒ Boolean
true
if we’re controlling a cluster. -
#initialize(argv) ⇒ Runner
constructor
A new instance of Runner.
-
#parse! ⇒ Object
Parse the options.
- #parser ⇒ Object
-
#run! ⇒ Object
Parse the current shell arguments and run the command.
-
#run_command ⇒ Object
Send the command to the controller: single instance or cluster.
-
#service? ⇒ Boolean
true
if we’re acting a as system service.
Constructor Details
#initialize(argv) ⇒ Runner
Returns a new instance of Runner.
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/thin/runner.rb', line 30 def initialize(argv) @argv = argv # Default options values @options = { :chdir => Dir.pwd, :environment => ENV['RACK_ENV'] || 'development', :address => '0.0.0.0', :port => Server::DEFAULT_PORT, :timeout => Server::DEFAULT_TIMEOUT, :log => 'log/thin.log', :pid => 'tmp/pids/thin.pid', :max_conns => Server::DEFAULT_MAXIMUM_CONNECTIONS, :max_persistent_conns => Server::DEFAULT_MAXIMUM_PERSISTENT_CONNECTIONS, :require => [], :wait => Controllers::Cluster::DEFAULT_WAIT_TIME } parse! end |
Instance Attribute Details
#arguments ⇒ Object
Arguments to be passed to the command.
21 22 23 |
# File 'lib/thin/runner.rb', line 21 def arguments @arguments end |
#command ⇒ Object
Name of the command to be runned.
18 19 20 |
# File 'lib/thin/runner.rb', line 18 def command @command end |
#options ⇒ Object
Parsed options
15 16 17 |
# File 'lib/thin/runner.rb', line 15 def @options end |
Class Method Details
.commands ⇒ Object
Return all available commands
24 25 26 27 28 |
# File 'lib/thin/runner.rb', line 24 def self.commands commands = COMMANDS commands += LINUX_ONLY_COMMANDS if Thin.linux? commands end |
Instance Method Details
#cluster? ⇒ Boolean
true
if we’re controlling a cluster.
197 198 199 |
# File 'lib/thin/runner.rb', line 197 def cluster? @options[:only] || @options[:servers] || @options[:config] end |
#parse! ⇒ Object
Parse the options.
142 143 144 145 146 |
# File 'lib/thin/runner.rb', line 142 def parse! parser.parse! @argv @command = @argv.shift @arguments = @argv end |
#parser ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/thin/runner.rb', line 51 def parser # NOTE: If you add an option here make sure the key in the +options+ hash is the # same as the name of the command line option. # +option+ keys are used to build the command line to launch other processes, # see <tt>lib/thin/command.rb</tt>. @parser ||= OptionParser.new do |opts| opts. = "Usage: thin [options] #{self.class.commands.join('|')}" opts.separator "" opts.separator "Server options:" opts.on("-a", "--address HOST", "bind to HOST address " + "(default: #{@options[:address]})") { |host| @options[:address] = host } opts.on("-p", "--port PORT", "use PORT (default: #{@options[:port]})") { |port| @options[:port] = port.to_i } opts.on("-S", "--socket FILE", "bind to unix domain socket") { |file| @options[:socket] = file } opts.on("-y", "--swiftiply [KEY]", "Run using swiftiply") { |key| @options[:swiftiply] = key } opts.on("-A", "--adapter NAME", "Rack adapter to use (default: autodetect)", "(#{Rack::ADAPTERS.map{|(a,b)|a}.join(', ')})") { |name| @options[:adapter] = name } opts.on("-R", "--rackup FILE", "Load a Rack config file instead of " + "Rack adapter") { |file| @options[:rackup] = file } opts.on("-c", "--chdir DIR", "Change to dir before starting") { |dir| @options[:chdir] = File.(dir) } opts.on( "--stats PATH", "Mount the Stats adapter under PATH") { |path| @options[:stats] = path } opts.separator "" opts.separator "SSL options:" opts.on( "--ssl", "Enables SSL") { @options[:ssl] = true } opts.on( "--ssl-key-file PATH", "Path to private key") { |path| @options[:ssl_key_file] = path } opts.on( "--ssl-cert-file PATH", "Path to certificate") { |path| @options[:ssl_cert_file] = path } opts.on( "--ssl-verify", "Enables SSL certificate verification") { @options[:ssl_verify] = true } opts.separator "" opts.separator "Adapter options:" opts.on("-e", "--environment ENV", "Framework environment " + "(default: #{@options[:environment]})") { |env| @options[:environment] = env } opts.on( "--prefix PATH", "Mount the app under PATH (start with /)") { |path| @options[:prefix] = path } unless Thin.win? # Daemonizing not supported on Windows opts.separator "" opts.separator "Daemon options:" opts.on("-d", "--daemonize", "Run daemonized in the background") { @options[:daemonize] = true } opts.on("-l", "--log FILE", "File to redirect output " + "(default: #{@options[:log]})") { |file| @options[:log] = file } opts.on("-P", "--pid FILE", "File to store PID " + "(default: #{@options[:pid]})") { |file| @options[:pid] = file } opts.on("-u", "--user NAME", "User to run daemon as (use with -g)") { |user| @options[:user] = user } opts.on("-g", "--group NAME", "Group to run daemon as (use with -u)") { |group| @options[:group] = group } opts.on( "--tag NAME", "Additional text to display in process listing") { |tag| @options[:tag] = tag } opts.separator "" opts.separator "Cluster options:" opts.on("-s", "--servers NUM", "Number of servers to start") { |num| @options[:servers] = num.to_i } opts.on("-o", "--only NUM", "Send command to only one server of the cluster") { |only| @options[:only] = only.to_i } opts.on("-C", "--config FILE", "Load options from config file") { |file| @options[:config] = file } opts.on( "--all [DIR]", "Send command to each config files in DIR") { |dir| @options[:all] = dir } if Thin.linux? opts.on("-O", "--onebyone", "Restart the cluster one by one (only works with restart command)") { @options[:onebyone] = true } opts.on("-w", "--wait NUM", "Maximum wait time for server to be started in seconds (use with -O)") { |time| @options[:wait] = time.to_i } end opts.separator "" opts.separator "Tuning options:" opts.on("-b", "--backend CLASS", "Backend to use, full classname") { |name| @options[:backend] = name } opts.on("-t", "--timeout SEC", "Request or command timeout in sec " + "(default: #{@options[:timeout]})") { |sec| @options[:timeout] = sec.to_i } opts.on("-f", "--force", "Force the execution of the command") { @options[:force] = true } opts.on( "--max-conns NUM", "Maximum number of open file descriptors " + "(default: #{@options[:max_conns]})", "Might require sudo to set higher than 1024") { |num| @options[:max_conns] = num.to_i } unless Thin.win? opts.on( "--max-persistent-conns NUM", "Maximum number of persistent connections", "(default: #{@options[:max_persistent_conns]})") { |num| @options[:max_persistent_conns] = num.to_i } opts.on( "--threaded", "Call the Rack application in threads " + "[experimental]") { @options[:threaded] = true } opts.on( "--no-epoll", "Disable the use of epoll") { @options[:no_epoll] = true } if Thin.linux? opts.separator "" opts.separator "Common options:" opts.on_tail("-r", "--require FILE", "require the library") { |file| @options[:require] << file } opts.on_tail("-q", "--quiet", "Silence all logging") { @options[:quiet] = true } opts.on_tail("-D", "--debug", "Set debugging on") { @options[:debug] = true } opts.on_tail("-V", "--trace", "Set tracing on (log raw request/response)") { @options[:trace] = true } opts.on_tail("-h", "--help", "Show this message") { puts opts; exit } opts.on_tail('-v', '--version', "Show version") { puts Thin::SERVER; exit } end end |
#run! ⇒ Object
Parse the current shell arguments and run the command. Exits on error.
150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/thin/runner.rb', line 150 def run! if self.class.commands.include?(@command) run_command elsif @command.nil? puts "Command required" puts @parser exit 1 else abort "Unknown command: #{@command}. Use one of #{self.class.commands.join(', ')}" end end |
#run_command ⇒ Object
Send the command to the controller: single instance or cluster.
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/thin/runner.rb', line 163 def run_command unless CONFIGLESS_COMMANDS.include?(@command) # PROGRAM_NAME is relative to the current directory, so make sure # we store and expand it before changing directory. Command.script = File.($PROGRAM_NAME) # Change the current directory ASAP so that all relative paths are # relative to this one. Dir.chdir(@options[:chdir]) unless CONFIGLESS_COMMANDS.include?(@command) @options[:require].each { |r| ruby_require r } Logging.debug = @options[:debug] Logging.trace = @options[:trace] Logging.silent = @options[:quiet] controller = case when cluster? then Controllers::Cluster.new(@options) when service? then Controllers::Service.new(@options) else Controllers::Controller.new(@options) end if controller.respond_to?(@command) begin controller.send(@command, *@arguments) rescue RunnerError => e abort e. end else abort "Invalid options for command: #{@command}" end end |
#service? ⇒ Boolean
true
if we’re acting a as system service.
202 203 204 |
# File 'lib/thin/runner.rb', line 202 def service? @options.has_key?(:all) || @command == 'install' end |