puma 2.16.0 → 3.11.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/{History.txt → History.md} +489 -70
- data/README.md +143 -174
- data/docs/architecture.md +36 -0
- data/{DEPLOYMENT.md → docs/deployment.md} +1 -1
- data/docs/images/puma-connection-flow-no-reactor.png +0 -0
- data/docs/images/puma-connection-flow.png +0 -0
- data/docs/images/puma-general-arch.png +0 -0
- data/docs/nginx.md +2 -2
- data/docs/plugins.md +28 -0
- data/docs/restart.md +39 -0
- data/docs/signals.md +56 -3
- data/docs/systemd.md +272 -0
- data/ext/puma_http11/extconf.rb +2 -0
- data/ext/puma_http11/http11_parser.c +291 -447
- data/ext/puma_http11/http11_parser.h +1 -0
- data/ext/puma_http11/http11_parser.java.rl +5 -5
- data/ext/puma_http11/http11_parser.rl +10 -9
- data/ext/puma_http11/http11_parser_common.rl +1 -1
- data/ext/puma_http11/io_buffer.c +8 -8
- data/ext/puma_http11/mini_ssl.c +64 -6
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +113 -131
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +9 -2
- data/ext/puma_http11/puma_http11.c +1 -0
- data/lib/puma/app/status.rb +9 -1
- data/lib/puma/binder.rb +90 -38
- data/lib/puma/cli.rb +134 -491
- data/lib/puma/client.rb +142 -4
- data/lib/puma/cluster.rb +132 -76
- data/lib/puma/commonlogger.rb +19 -20
- data/lib/puma/compat.rb +3 -7
- data/lib/puma/configuration.rb +206 -67
- data/lib/puma/const.rb +21 -31
- data/lib/puma/control_cli.rb +92 -103
- data/lib/puma/convenient.rb +23 -0
- data/lib/puma/daemon_ext.rb +6 -0
- data/lib/puma/detect.rb +10 -1
- data/lib/puma/dsl.rb +203 -45
- data/lib/puma/events.rb +22 -13
- data/lib/puma/io_buffer.rb +1 -1
- data/lib/puma/jruby_restart.rb +1 -2
- data/lib/puma/launcher.rb +431 -0
- data/lib/puma/minissl.rb +83 -4
- data/lib/puma/null_io.rb +19 -11
- data/lib/puma/plugin/tmp_restart.rb +34 -0
- data/lib/puma/plugin.rb +115 -0
- data/lib/puma/rack/backports/uri/common_193.rb +17 -13
- data/lib/puma/rack/builder.rb +3 -0
- data/lib/puma/rack/urlmap.rb +9 -8
- data/lib/puma/reactor.rb +18 -0
- data/lib/puma/runner.rb +43 -15
- data/lib/puma/server.rb +141 -35
- data/lib/puma/single.rb +16 -6
- data/lib/puma/state_file.rb +29 -0
- data/lib/puma/tcp_logger.rb +8 -1
- data/lib/puma/thread_pool.rb +60 -10
- data/lib/puma/util.rb +1 -5
- data/lib/puma.rb +13 -4
- data/lib/rack/handler/puma.rb +76 -29
- data/tools/jungle/README.md +12 -2
- data/tools/jungle/init.d/README.md +9 -2
- data/tools/jungle/init.d/puma +86 -59
- data/tools/jungle/init.d/run-puma +16 -1
- data/tools/jungle/rc.d/README.md +74 -0
- data/tools/jungle/rc.d/puma +61 -0
- data/tools/jungle/rc.d/puma.conf +10 -0
- data/tools/jungle/upstart/puma.conf +1 -1
- data/tools/trickletest.rb +1 -1
- metadata +28 -95
- data/COPYING +0 -55
- data/Gemfile +0 -13
- data/Manifest.txt +0 -74
- data/Rakefile +0 -158
- data/docs/config.md +0 -0
- data/lib/puma/capistrano.rb +0 -94
- data/lib/puma/rack/backports/uri/common_18.rb +0 -56
- data/lib/puma/rack/backports/uri/common_192.rb +0 -52
- data/puma.gemspec +0 -52
data/lib/puma/cli.rb
CHANGED
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
require 'optparse'
|
|
2
2
|
require 'uri'
|
|
3
3
|
|
|
4
|
-
require 'puma
|
|
5
|
-
require 'puma/const'
|
|
4
|
+
require 'puma'
|
|
6
5
|
require 'puma/configuration'
|
|
7
|
-
require 'puma/
|
|
8
|
-
require 'puma/
|
|
9
|
-
require 'puma/
|
|
10
|
-
require 'puma/util'
|
|
11
|
-
require 'puma/single'
|
|
12
|
-
require 'puma/cluster'
|
|
13
|
-
|
|
14
|
-
require 'puma/commonlogger'
|
|
6
|
+
require 'puma/launcher'
|
|
7
|
+
require 'puma/const'
|
|
8
|
+
require 'puma/events'
|
|
15
9
|
|
|
16
10
|
module Puma
|
|
17
11
|
class << self
|
|
@@ -25,11 +19,7 @@ module Puma
|
|
|
25
19
|
# Handles invoke a Puma::Server in a command line style.
|
|
26
20
|
#
|
|
27
21
|
class CLI
|
|
28
|
-
KEYS_NOT_TO_PERSIST_IN_STATE =
|
|
29
|
-
:logger, :lowlevel_error_handler,
|
|
30
|
-
:before_worker_shutdown, :before_worker_boot, :before_worker_fork,
|
|
31
|
-
:after_worker_boot, :before_fork, :on_restart
|
|
32
|
-
]
|
|
22
|
+
KEYS_NOT_TO_PERSIST_IN_STATE = Launcher::KEYS_NOT_TO_PERSIST_IN_STATE
|
|
33
23
|
|
|
34
24
|
# Create a new CLI object using +argv+ as the command line
|
|
35
25
|
# arguments.
|
|
@@ -39,544 +29,197 @@ module Puma
|
|
|
39
29
|
#
|
|
40
30
|
def initialize(argv, events=Events.stdio)
|
|
41
31
|
@debug = false
|
|
42
|
-
@argv = argv
|
|
32
|
+
@argv = argv.dup
|
|
43
33
|
|
|
44
34
|
@events = events
|
|
45
35
|
|
|
46
|
-
@
|
|
47
|
-
@runner = nil
|
|
48
|
-
|
|
49
|
-
@config = nil
|
|
36
|
+
@conf = nil
|
|
50
37
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
@binder = Binder.new(@events)
|
|
55
|
-
@binder.import_from_env
|
|
56
|
-
end
|
|
38
|
+
@stdout = nil
|
|
39
|
+
@stderr = nil
|
|
40
|
+
@append = false
|
|
57
41
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
# The Configuration object used.
|
|
62
|
-
attr_reader :config
|
|
63
|
-
|
|
64
|
-
# The Hash of options used to configure puma.
|
|
65
|
-
attr_reader :options
|
|
66
|
-
|
|
67
|
-
# The Events object used to output information.
|
|
68
|
-
attr_reader :events
|
|
69
|
-
|
|
70
|
-
# Delegate +log+ to +@events+
|
|
71
|
-
#
|
|
72
|
-
def log(str)
|
|
73
|
-
@events.log str
|
|
74
|
-
end
|
|
42
|
+
@control_url = nil
|
|
43
|
+
@control_options = {}
|
|
75
44
|
|
|
76
|
-
|
|
77
|
-
#
|
|
78
|
-
def error(str)
|
|
79
|
-
@events.error str
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def debug(str)
|
|
83
|
-
@events.log "- #{str}" if @options[:debug]
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
def clustered?
|
|
87
|
-
@options[:workers] > 0
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def prune_bundler?
|
|
91
|
-
@options[:prune_bundler] && clustered? && !@options[:preload_app]
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
def jruby?
|
|
95
|
-
IS_JRUBY
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def windows?
|
|
99
|
-
RUBY_PLATFORM =~ /mswin32|ming32/
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
def env
|
|
103
|
-
@options[:environment] || @cli_options[:environment] || ENV['RACK_ENV'] || 'development'
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
def write_state
|
|
107
|
-
write_pid
|
|
108
|
-
|
|
109
|
-
path = @options[:state]
|
|
110
|
-
return unless path
|
|
111
|
-
|
|
112
|
-
state = { 'pid' => Process.pid }
|
|
113
|
-
cfg = @config.dup
|
|
114
|
-
|
|
115
|
-
KEYS_NOT_TO_PERSIST_IN_STATE.each { |k| cfg.options.delete(k) }
|
|
116
|
-
state['config'] = cfg
|
|
117
|
-
|
|
118
|
-
require 'yaml'
|
|
119
|
-
File.open(path, 'w') { |f| f.write state.to_yaml }
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
# If configured, write the pid of the current process out
|
|
123
|
-
# to a file.
|
|
124
|
-
#
|
|
125
|
-
def write_pid
|
|
126
|
-
path = @options[:pidfile]
|
|
127
|
-
return unless path
|
|
128
|
-
|
|
129
|
-
File.open(path, 'w') { |f| f.puts Process.pid }
|
|
130
|
-
cur = Process.pid
|
|
131
|
-
at_exit do
|
|
132
|
-
delete_pidfile if cur == Process.pid
|
|
133
|
-
end
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
def delete_pidfile
|
|
137
|
-
path = @options[:pidfile]
|
|
138
|
-
File.unlink(path) if path && File.exist?(path)
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
def graceful_stop
|
|
142
|
-
@runner.stop_blocked
|
|
143
|
-
log "=== puma shutdown: #{Time.now} ==="
|
|
144
|
-
log "- Goodbye!"
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
def jruby_daemon_start
|
|
148
|
-
require 'puma/jruby_restart'
|
|
149
|
-
JRubyRestart.daemon_start(@restart_dir, restart_args)
|
|
150
|
-
end
|
|
45
|
+
setup_options
|
|
151
46
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
block.call self
|
|
155
|
-
end
|
|
47
|
+
begin
|
|
48
|
+
@parser.parse! @argv
|
|
156
49
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
JRubyRestart.chdir_exec(@restart_dir, restart_args)
|
|
162
|
-
elsif windows?
|
|
163
|
-
close_binder_listeners
|
|
164
|
-
|
|
165
|
-
argv = restart_args
|
|
166
|
-
Dir.chdir(@restart_dir)
|
|
167
|
-
argv += [redirects] if RUBY_VERSION >= '1.9'
|
|
168
|
-
Kernel.exec(*argv)
|
|
169
|
-
else
|
|
170
|
-
redirects = {:close_others => true}
|
|
171
|
-
@binder.listeners.each_with_index do |(l, io), i|
|
|
172
|
-
ENV["PUMA_INHERIT_#{i}"] = "#{io.to_i}:#{l}"
|
|
173
|
-
redirects[io.to_i] = io.to_i
|
|
50
|
+
if file = @argv.shift
|
|
51
|
+
@conf.configure do |user_config, file_config|
|
|
52
|
+
file_config.rackup file
|
|
53
|
+
end
|
|
174
54
|
end
|
|
175
|
-
|
|
176
|
-
argv = restart_args
|
|
177
|
-
Dir.chdir(@restart_dir)
|
|
178
|
-
argv += [redirects] if RUBY_VERSION >= '1.9'
|
|
179
|
-
Kernel.exec(*argv)
|
|
180
|
-
end
|
|
181
|
-
end
|
|
182
|
-
|
|
183
|
-
# Parse the options, load the rackup, start the server and wait
|
|
184
|
-
# for it to finish.
|
|
185
|
-
#
|
|
186
|
-
def run
|
|
187
|
-
begin
|
|
188
|
-
parse_options
|
|
189
55
|
rescue UnsupportedOption
|
|
190
56
|
exit 1
|
|
191
57
|
end
|
|
192
58
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
set_rack_environment
|
|
199
|
-
|
|
200
|
-
if clustered?
|
|
201
|
-
@events.formatter = Events::PidFormatter.new
|
|
202
|
-
@options[:logger] = @events
|
|
203
|
-
|
|
204
|
-
@runner = Cluster.new(self)
|
|
205
|
-
else
|
|
206
|
-
@runner = Single.new(self)
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
setup_signals
|
|
210
|
-
set_process_title
|
|
211
|
-
|
|
212
|
-
@status = :run
|
|
213
|
-
|
|
214
|
-
@runner.run
|
|
215
|
-
|
|
216
|
-
case @status
|
|
217
|
-
when :halt
|
|
218
|
-
log "* Stopping immediately!"
|
|
219
|
-
when :run, :stop
|
|
220
|
-
graceful_stop
|
|
221
|
-
when :restart
|
|
222
|
-
log "* Restarting..."
|
|
223
|
-
@runner.before_restart
|
|
224
|
-
restart!
|
|
225
|
-
when :exit
|
|
226
|
-
# nothing
|
|
227
|
-
end
|
|
228
|
-
end
|
|
229
|
-
|
|
230
|
-
def stop
|
|
231
|
-
@status = :stop
|
|
232
|
-
@runner.stop
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
def restart
|
|
236
|
-
@status = :restart
|
|
237
|
-
@runner.restart
|
|
238
|
-
end
|
|
239
|
-
|
|
240
|
-
def reload_worker_directory
|
|
241
|
-
@runner.reload_worker_directory if @runner.respond_to?(:reload_worker_directory)
|
|
242
|
-
end
|
|
59
|
+
@conf.configure do |user_config, file_config|
|
|
60
|
+
if @stdout || @stderr
|
|
61
|
+
user_config.stdout_redirect @stdout, @stderr, @append
|
|
62
|
+
end
|
|
243
63
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
return restart
|
|
64
|
+
if @control_url
|
|
65
|
+
user_config.activate_control_app @control_url, @control_options
|
|
66
|
+
end
|
|
248
67
|
end
|
|
249
|
-
true
|
|
250
|
-
end
|
|
251
68
|
|
|
252
|
-
|
|
253
|
-
@runner.redirect_io
|
|
69
|
+
@launcher = Puma::Launcher.new(@conf, :events => @events, :argv => argv)
|
|
254
70
|
end
|
|
255
71
|
|
|
256
|
-
|
|
257
|
-
@runner.stats
|
|
258
|
-
end
|
|
72
|
+
attr_reader :launcher
|
|
259
73
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
74
|
+
# Parse the options, load the rackup, start the server and wait
|
|
75
|
+
# for it to finish.
|
|
76
|
+
#
|
|
77
|
+
def run
|
|
78
|
+
@launcher.run
|
|
263
79
|
end
|
|
264
80
|
|
|
265
81
|
private
|
|
266
|
-
def title
|
|
267
|
-
buffer = "puma #{Puma::Const::VERSION} (#{@options[:binds].join(',')})"
|
|
268
|
-
buffer << " [#{@options[:tag]}]" if @options[:tag] && !@options[:tag].empty?
|
|
269
|
-
buffer
|
|
270
|
-
end
|
|
271
|
-
|
|
272
82
|
def unsupported(str)
|
|
273
83
|
@events.error(str)
|
|
274
84
|
raise UnsupportedOption
|
|
275
85
|
end
|
|
276
86
|
|
|
277
|
-
def restart_args
|
|
278
|
-
cmd = @options[:restart_cmd]
|
|
279
|
-
if cmd
|
|
280
|
-
cmd.split(' ') + @original_argv
|
|
281
|
-
else
|
|
282
|
-
@restart_argv
|
|
283
|
-
end
|
|
284
|
-
end
|
|
285
|
-
|
|
286
|
-
def set_process_title
|
|
287
|
-
Process.respond_to?(:setproctitle) ? Process.setproctitle(title) : $0 = title
|
|
288
|
-
end
|
|
289
|
-
|
|
290
|
-
def find_config
|
|
291
|
-
if @cli_options[:config_file] == '-'
|
|
292
|
-
@cli_options[:config_file] = nil
|
|
293
|
-
else
|
|
294
|
-
@cli_options[:config_file] ||= %W(config/puma/#{env}.rb config/puma.rb).find { |f| File.exist?(f) }
|
|
295
|
-
end
|
|
296
|
-
end
|
|
297
|
-
|
|
298
87
|
# Build the OptionParser object to handle the available options.
|
|
299
88
|
#
|
|
300
89
|
|
|
301
90
|
def setup_options
|
|
302
|
-
@
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
o.on "-b", "--bind URI", "URI to bind to (tcp://, unix://, ssl://)" do |arg|
|
|
307
|
-
(@cli_options[:binds] ||= []) << arg
|
|
308
|
-
end
|
|
309
|
-
|
|
310
|
-
o.on "-C", "--config PATH", "Load PATH as a config file" do |arg|
|
|
311
|
-
@cli_options[:config_file] = arg
|
|
312
|
-
end
|
|
313
|
-
|
|
314
|
-
o.on "--control URL", "The bind url to use for the control server",
|
|
315
|
-
"Use 'auto' to use temp unix server" do |arg|
|
|
316
|
-
if arg
|
|
317
|
-
@cli_options[:control_url] = arg
|
|
318
|
-
elsif jruby?
|
|
319
|
-
unsupported "No default url available on JRuby"
|
|
91
|
+
@conf = Configuration.new do |user_config, file_config|
|
|
92
|
+
@parser = OptionParser.new do |o|
|
|
93
|
+
o.on "-b", "--bind URI", "URI to bind to (tcp://, unix://, ssl://)" do |arg|
|
|
94
|
+
user_config.bind arg
|
|
320
95
|
end
|
|
321
|
-
end
|
|
322
|
-
|
|
323
|
-
o.on "--control-token TOKEN",
|
|
324
|
-
"The token to use as authentication for the control server" do |arg|
|
|
325
|
-
@cli_options[:control_auth_token] = arg
|
|
326
|
-
end
|
|
327
|
-
|
|
328
|
-
o.on "-d", "--daemon", "Daemonize the server into the background" do
|
|
329
|
-
@cli_options[:daemon] = true
|
|
330
|
-
@cli_options[:quiet] = true
|
|
331
|
-
end
|
|
332
|
-
|
|
333
|
-
o.on "--debug", "Log lowlevel debugging information" do
|
|
334
|
-
@cli_options[:debug] = true
|
|
335
|
-
end
|
|
336
|
-
|
|
337
|
-
o.on "--dir DIR", "Change to DIR before starting" do |d|
|
|
338
|
-
@cli_options[:directory] = d.to_s
|
|
339
|
-
@cli_options[:worker_directory] = d.to_s
|
|
340
|
-
end
|
|
341
|
-
|
|
342
|
-
o.on "-e", "--environment ENVIRONMENT",
|
|
343
|
-
"The environment to run the Rack app on (default development)" do |arg|
|
|
344
|
-
@cli_options[:environment] = arg
|
|
345
|
-
end
|
|
346
|
-
|
|
347
|
-
o.on "-I", "--include PATH", "Specify $LOAD_PATH directories" do |arg|
|
|
348
|
-
$LOAD_PATH.unshift(*arg.split(':'))
|
|
349
|
-
end
|
|
350
|
-
|
|
351
|
-
o.on "-p", "--port PORT", "Define the TCP port to bind to",
|
|
352
|
-
"Use -b for more advanced options" do |arg|
|
|
353
|
-
binds = (@cli_options[:binds] ||= [])
|
|
354
|
-
binds << "tcp://#{Configuration::DefaultTCPHost}:#{arg}"
|
|
355
|
-
end
|
|
356
96
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
o.on "--preload", "Preload the app. Cluster mode only" do
|
|
362
|
-
@cli_options[:preload_app] = true
|
|
363
|
-
end
|
|
364
|
-
|
|
365
|
-
o.on "--prune-bundler", "Prune out the bundler env if possible" do
|
|
366
|
-
@cli_options[:prune_bundler] = true
|
|
367
|
-
end
|
|
97
|
+
o.on "-C", "--config PATH", "Load PATH as a config file" do |arg|
|
|
98
|
+
file_config.load arg
|
|
99
|
+
end
|
|
368
100
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
101
|
+
o.on "--control URL", "The bind url to use for the control server",
|
|
102
|
+
"Use 'auto' to use temp unix server" do |arg|
|
|
103
|
+
if arg
|
|
104
|
+
@control_url = arg
|
|
105
|
+
elsif Puma.jruby?
|
|
106
|
+
unsupported "No default url available on JRuby"
|
|
107
|
+
end
|
|
108
|
+
end
|
|
372
109
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
end
|
|
110
|
+
o.on "--control-token TOKEN",
|
|
111
|
+
"The token to use as authentication for the control server" do |arg|
|
|
112
|
+
@control_options[:auth_token] = arg
|
|
113
|
+
end
|
|
378
114
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
115
|
+
o.on "-d", "--daemon", "Daemonize the server into the background" do
|
|
116
|
+
user_config.daemonize
|
|
117
|
+
user_config.quiet
|
|
118
|
+
end
|
|
382
119
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
if max
|
|
386
|
-
@cli_options[:min_threads] = min
|
|
387
|
-
@cli_options[:max_threads] = max
|
|
388
|
-
else
|
|
389
|
-
@cli_options[:min_threads] = 0
|
|
390
|
-
@cli_options[:max_threads] = arg
|
|
120
|
+
o.on "--debug", "Log lowlevel debugging information" do
|
|
121
|
+
user_config.debug
|
|
391
122
|
end
|
|
392
|
-
end
|
|
393
123
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
124
|
+
o.on "--dir DIR", "Change to DIR before starting" do |d|
|
|
125
|
+
user_config.directory d
|
|
126
|
+
end
|
|
397
127
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
128
|
+
o.on "-e", "--environment ENVIRONMENT",
|
|
129
|
+
"The environment to run the Rack app on (default development)" do |arg|
|
|
130
|
+
user_config.environment arg
|
|
131
|
+
end
|
|
402
132
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
end
|
|
133
|
+
o.on "-I", "--include PATH", "Specify $LOAD_PATH directories" do |arg|
|
|
134
|
+
$LOAD_PATH.unshift(*arg.split(':'))
|
|
135
|
+
end
|
|
407
136
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
137
|
+
o.on "-p", "--port PORT", "Define the TCP port to bind to",
|
|
138
|
+
"Use -b for more advanced options" do |arg|
|
|
139
|
+
user_config.bind "tcp://#{Configuration::DefaultTCPHost}:#{arg}"
|
|
140
|
+
end
|
|
411
141
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
142
|
+
o.on "--pidfile PATH", "Use PATH as a pidfile" do |arg|
|
|
143
|
+
user_config.pidfile arg
|
|
144
|
+
end
|
|
415
145
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
146
|
+
o.on "--preload", "Preload the app. Cluster mode only" do
|
|
147
|
+
user_config.preload_app!
|
|
148
|
+
end
|
|
419
149
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
150
|
+
o.on "--prune-bundler", "Prune out the bundler env if possible" do
|
|
151
|
+
user_config.prune_bundler
|
|
152
|
+
end
|
|
423
153
|
|
|
424
|
-
|
|
154
|
+
o.on "-q", "--quiet", "Do not log requests internally (default true)" do
|
|
155
|
+
user_config.quiet
|
|
156
|
+
end
|
|
425
157
|
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
end
|
|
430
|
-
end
|
|
431
|
-
end
|
|
158
|
+
o.on "-v", "--log-requests", "Log requests as they occur" do
|
|
159
|
+
user_config.log_requests
|
|
160
|
+
end
|
|
432
161
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
s_env = File.stat(dir)
|
|
439
|
-
s_pwd = File.stat(Dir.pwd)
|
|
440
|
-
|
|
441
|
-
if s_env.ino == s_pwd.ino and (jruby? or s_env.dev == s_pwd.dev)
|
|
442
|
-
@restart_dir = dir
|
|
443
|
-
@options[:worker_directory] = dir
|
|
444
|
-
end
|
|
445
|
-
end
|
|
162
|
+
o.on "-R", "--restart-cmd CMD",
|
|
163
|
+
"The puma command to run during a hot restart",
|
|
164
|
+
"Default: inferred" do |cmd|
|
|
165
|
+
user_config.restart_command cmd
|
|
166
|
+
end
|
|
446
167
|
|
|
447
|
-
|
|
168
|
+
o.on "-S", "--state PATH", "Where to store the state details" do |arg|
|
|
169
|
+
user_config.state_path arg
|
|
170
|
+
end
|
|
448
171
|
|
|
449
|
-
|
|
172
|
+
o.on '-t', '--threads INT', "min:max threads to use (default 0:16)" do |arg|
|
|
173
|
+
min, max = arg.split(":")
|
|
174
|
+
if max
|
|
175
|
+
user_config.threads min, max
|
|
176
|
+
else
|
|
177
|
+
user_config.threads min, min
|
|
178
|
+
end
|
|
179
|
+
end
|
|
450
180
|
|
|
451
|
-
|
|
181
|
+
o.on "--tcp-mode", "Run the app in raw TCP mode instead of HTTP mode" do
|
|
182
|
+
user_config.tcp_mode!
|
|
183
|
+
end
|
|
452
184
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
#
|
|
457
|
-
if File.exist?($0)
|
|
458
|
-
arg0 = [Gem.ruby, $0]
|
|
459
|
-
else
|
|
460
|
-
arg0 = [Gem.ruby, "-S", $0]
|
|
461
|
-
end
|
|
185
|
+
o.on "--early-hints", "Enable early hints support" do
|
|
186
|
+
user_config.early_hints
|
|
187
|
+
end
|
|
462
188
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
189
|
+
o.on "-V", "--version", "Print the version information" do
|
|
190
|
+
puts "puma version #{Puma::Const::VERSION}"
|
|
191
|
+
exit 0
|
|
192
|
+
end
|
|
466
193
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
end
|
|
472
|
-
end
|
|
194
|
+
o.on "-w", "--workers COUNT",
|
|
195
|
+
"Activate cluster mode: How many worker processes to create" do |arg|
|
|
196
|
+
user_config.workers arg
|
|
197
|
+
end
|
|
473
198
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
end
|
|
199
|
+
o.on "--tag NAME", "Additional text to display in process listing" do |arg|
|
|
200
|
+
user_config.tag arg
|
|
201
|
+
end
|
|
478
202
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
restart
|
|
483
|
-
end
|
|
484
|
-
rescue Exception
|
|
485
|
-
log "*** SIGUSR2 not implemented, signal based restart unavailable!"
|
|
486
|
-
end
|
|
203
|
+
o.on "--redirect-stdout FILE", "Redirect STDOUT to a specific file" do |arg|
|
|
204
|
+
@stdout = arg.to_s
|
|
205
|
+
end
|
|
487
206
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
end
|
|
492
|
-
rescue Exception
|
|
493
|
-
log "*** SIGUSR1 not implemented, signal based restart unavailable!"
|
|
494
|
-
end
|
|
207
|
+
o.on "--redirect-stderr FILE", "Redirect STDERR to a specific file" do |arg|
|
|
208
|
+
@stderr = arg.to_s
|
|
209
|
+
end
|
|
495
210
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
end
|
|
500
|
-
rescue Exception
|
|
501
|
-
log "*** SIGTERM not implemented, signal based gracefully stopping unavailable!"
|
|
502
|
-
end
|
|
211
|
+
o.on "--[no-]redirect-append", "Append to redirected files" do |val|
|
|
212
|
+
@append = val
|
|
213
|
+
end
|
|
503
214
|
|
|
504
|
-
|
|
505
|
-
Signal.trap "SIGHUP" do
|
|
506
|
-
redirect_io
|
|
507
|
-
end
|
|
508
|
-
rescue Exception
|
|
509
|
-
log "*** SIGHUP not implemented, signal based logs reopening unavailable!"
|
|
510
|
-
end
|
|
215
|
+
o.banner = "puma <options> <rackup file>"
|
|
511
216
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
exit
|
|
217
|
+
o.on_tail "-h", "--help", "Show help" do
|
|
218
|
+
$stdout.puts o
|
|
219
|
+
exit 0
|
|
220
|
+
end
|
|
517
221
|
end
|
|
518
222
|
end
|
|
519
223
|
end
|
|
520
|
-
|
|
521
|
-
def close_binder_listeners
|
|
522
|
-
@binder.listeners.each do |l, io|
|
|
523
|
-
io.close
|
|
524
|
-
uri = URI.parse(l)
|
|
525
|
-
next unless uri.scheme == 'unix'
|
|
526
|
-
File.unlink("#{uri.host}#{uri.path}")
|
|
527
|
-
end
|
|
528
|
-
end
|
|
529
|
-
|
|
530
|
-
def parse_options
|
|
531
|
-
@parser.parse! @argv
|
|
532
|
-
|
|
533
|
-
@cli_options[:rackup] = @argv.shift if @argv.last
|
|
534
|
-
|
|
535
|
-
find_config
|
|
536
|
-
|
|
537
|
-
@config = Puma::Configuration.new @cli_options
|
|
538
|
-
|
|
539
|
-
# Advertise the Configuration
|
|
540
|
-
Puma.cli_config = @config
|
|
541
|
-
|
|
542
|
-
@config.load
|
|
543
|
-
|
|
544
|
-
@options = @config.options
|
|
545
|
-
|
|
546
|
-
if clustered? && (jruby? || windows?)
|
|
547
|
-
unsupported 'worker mode not supported on JRuby or Windows'
|
|
548
|
-
end
|
|
549
|
-
|
|
550
|
-
if @options[:daemon] && windows?
|
|
551
|
-
unsupported 'daemon mode not supported on Windows'
|
|
552
|
-
end
|
|
553
|
-
end
|
|
554
|
-
|
|
555
|
-
def prune_bundler
|
|
556
|
-
return unless defined?(Bundler)
|
|
557
|
-
puma = Bundler.rubygems.loaded_specs("puma")
|
|
558
|
-
dirs = puma.require_paths.map { |x| File.join(puma.full_gem_path, x) }
|
|
559
|
-
puma_lib_dir = dirs.detect { |x| File.exist? File.join(x, '../bin/puma-wild') }
|
|
560
|
-
|
|
561
|
-
unless puma_lib_dir
|
|
562
|
-
log "! Unable to prune Bundler environment, continuing"
|
|
563
|
-
return
|
|
564
|
-
end
|
|
565
|
-
|
|
566
|
-
deps = puma.runtime_dependencies.map do |d|
|
|
567
|
-
spec = Bundler.rubygems.loaded_specs(d.name)
|
|
568
|
-
"#{d.name}:#{spec.version.to_s}"
|
|
569
|
-
end
|
|
570
|
-
|
|
571
|
-
log '* Pruning Bundler environment'
|
|
572
|
-
home = ENV['GEM_HOME']
|
|
573
|
-
Bundler.with_clean_env do
|
|
574
|
-
ENV['GEM_HOME'] = home
|
|
575
|
-
ENV['PUMA_BUNDLER_PRUNED'] = '1'
|
|
576
|
-
wild = File.expand_path(File.join(puma_lib_dir, "../bin/puma-wild"))
|
|
577
|
-
args = [Gem.ruby, wild, '-I', dirs.join(':'), deps.join(',')] + @original_argv
|
|
578
|
-
Kernel.exec(*args)
|
|
579
|
-
end
|
|
580
|
-
end
|
|
581
224
|
end
|
|
582
225
|
end
|