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