puma 3.4.0 → 3.12.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puma might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/{History.txt → History.md} +356 -74
- data/README.md +143 -227
- 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/plugins.md +28 -0
- data/docs/restart.md +39 -0
- data/docs/signals.md +56 -3
- data/docs/systemd.md +124 -22
- 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.rl +10 -9
- data/ext/puma_http11/http11_parser_common.rl +1 -1
- data/ext/puma_http11/io_buffer.c +7 -7
- data/ext/puma_http11/mini_ssl.c +67 -6
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +76 -94
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +15 -2
- data/ext/puma_http11/puma_http11.c +1 -0
- data/lib/puma.rb +13 -5
- data/lib/puma/app/status.rb +8 -0
- data/lib/puma/binder.rb +46 -21
- data/lib/puma/cli.rb +49 -33
- data/lib/puma/client.rb +149 -4
- data/lib/puma/cluster.rb +55 -13
- data/lib/puma/commonlogger.rb +19 -20
- data/lib/puma/compat.rb +3 -7
- data/lib/puma/configuration.rb +136 -131
- data/lib/puma/const.rb +19 -37
- data/lib/puma/control_cli.rb +38 -35
- data/lib/puma/convenient.rb +3 -3
- data/lib/puma/detect.rb +3 -1
- data/lib/puma/dsl.rb +86 -57
- data/lib/puma/events.rb +17 -13
- data/lib/puma/io_buffer.rb +1 -1
- data/lib/puma/jruby_restart.rb +0 -1
- data/lib/puma/launcher.rb +61 -30
- data/lib/puma/minissl.rb +85 -4
- data/lib/puma/null_io.rb +6 -13
- data/lib/puma/plugin.rb +12 -1
- data/lib/puma/plugin/tmp_restart.rb +1 -2
- data/lib/puma/rack/builder.rb +3 -0
- data/lib/puma/rack/urlmap.rb +9 -8
- data/lib/puma/reactor.rb +144 -0
- data/lib/puma/runner.rb +27 -1
- data/lib/puma/server.rb +135 -33
- data/lib/puma/single.rb +17 -3
- data/lib/puma/tcp_logger.rb +8 -1
- data/lib/puma/thread_pool.rb +70 -20
- data/lib/puma/util.rb +1 -5
- data/lib/rack/handler/puma.rb +58 -17
- data/tools/jungle/README.md +12 -2
- data/tools/jungle/init.d/README.md +9 -2
- data/tools/jungle/init.d/puma +85 -58
- 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 +22 -94
- data/Gemfile +0 -13
- data/Manifest.txt +0 -78
- data/Rakefile +0 -158
- data/docs/config.md +0 -0
- data/lib/puma/rack/backports/uri/common_18.rb +0 -59
- data/lib/puma/rack/backports/uri/common_192.rb +0 -55
- data/puma.gemspec +0 -52
data/lib/puma/single.rb
CHANGED
@@ -1,11 +1,22 @@
|
|
1
1
|
require 'puma/runner'
|
2
|
+
require 'puma/detect'
|
3
|
+
require 'puma/plugin'
|
2
4
|
|
3
5
|
module Puma
|
6
|
+
# This class is instantiated by the `Puma::Launcher` and used
|
7
|
+
# to boot and serve a Ruby application when no puma "workers" are needed
|
8
|
+
# i.e. only using "threaded" mode. For example `$ puma -t 1:5`
|
9
|
+
#
|
10
|
+
# At the core of this class is running an instance of `Puma::Server` which
|
11
|
+
# gets created via the `start_server` method from the `Puma::Runner` class
|
12
|
+
# that this inherits from.
|
4
13
|
class Single < Runner
|
5
14
|
def stats
|
6
|
-
b = @server.backlog
|
7
|
-
r = @server.running
|
8
|
-
|
15
|
+
b = @server.backlog || 0
|
16
|
+
r = @server.running || 0
|
17
|
+
t = @server.pool_capacity || 0
|
18
|
+
m = @server.max_threads || 0
|
19
|
+
%Q!{ "backlog": #{b}, "running": #{r}, "pool_capacity": #{t}, "max_threads": #{m} }!
|
9
20
|
end
|
10
21
|
|
11
22
|
def restart
|
@@ -44,6 +55,7 @@ module Puma
|
|
44
55
|
if JRubyRestart.daemon?
|
45
56
|
# load and bind before redirecting IO so errors show up on stdout/stderr
|
46
57
|
load_and_bind
|
58
|
+
redirect_io
|
47
59
|
end
|
48
60
|
|
49
61
|
already_daemon = JRubyRestart.daemon_init
|
@@ -84,6 +96,8 @@ module Puma
|
|
84
96
|
load_and_bind
|
85
97
|
end
|
86
98
|
|
99
|
+
Plugins.fire_background
|
100
|
+
|
87
101
|
@launcher.write_state
|
88
102
|
|
89
103
|
start_control
|
data/lib/puma/tcp_logger.rb
CHANGED
@@ -11,7 +11,14 @@ module Puma
|
|
11
11
|
def log(who, str)
|
12
12
|
now = Time.now.strftime("%d/%b/%Y %H:%M:%S")
|
13
13
|
|
14
|
-
|
14
|
+
log_str = "#{now} - #{who} - #{str}"
|
15
|
+
|
16
|
+
case @logger
|
17
|
+
when IO
|
18
|
+
@logger.puts log_str
|
19
|
+
when Events
|
20
|
+
@logger.log log_str
|
21
|
+
end
|
15
22
|
end
|
16
23
|
|
17
24
|
def call(env, socket)
|
data/lib/puma/thread_pool.rb
CHANGED
@@ -1,13 +1,26 @@
|
|
1
1
|
require 'thread'
|
2
2
|
|
3
3
|
module Puma
|
4
|
-
# A simple thread pool management object.
|
4
|
+
# Internal Docs for A simple thread pool management object.
|
5
5
|
#
|
6
|
+
# Each Puma "worker" has a thread pool to process requests.
|
7
|
+
#
|
8
|
+
# First a connection to a client is made in `Puma::Server`. It is wrapped in a
|
9
|
+
# `Puma::Client` instance and then passed to the `Puma::Reactor` to ensure
|
10
|
+
# the whole request is buffered into memory. Once the request is ready, it is passed into
|
11
|
+
# a thread pool via the `Puma::ThreadPool#<<` operator where it is stored in a `@todo` array.
|
12
|
+
#
|
13
|
+
# Each thread in the pool has an internal loop where it pulls a request from the `@todo` array
|
14
|
+
# and proceses it.
|
6
15
|
class ThreadPool
|
7
|
-
|
8
16
|
class ForceShutdown < RuntimeError
|
9
17
|
end
|
10
18
|
|
19
|
+
# How long, after raising the ForceShutdown of a thread during
|
20
|
+
# forced shutdown mode, to wait for the thread to try and finish
|
21
|
+
# up its work before leaving the thread to die on the vine.
|
22
|
+
SHUTDOWN_GRACE_TIME = 5 # seconds
|
23
|
+
|
11
24
|
# Maintain a minimum of +min+ and maximum of +max+ threads
|
12
25
|
# in the pool.
|
13
26
|
#
|
@@ -45,11 +58,11 @@ module Puma
|
|
45
58
|
@clean_thread_locals = false
|
46
59
|
end
|
47
60
|
|
48
|
-
attr_reader :spawned, :trim_requested
|
61
|
+
attr_reader :spawned, :trim_requested, :waiting
|
49
62
|
attr_accessor :clean_thread_locals
|
50
63
|
|
51
64
|
def self.clean_thread_locals
|
52
|
-
Thread.current.keys.each do |key|
|
65
|
+
Thread.current.keys.each do |key| # rubocop: disable Performance/HashEachMethods
|
53
66
|
Thread.current[key] = nil unless key == :__recursive_key__
|
54
67
|
end
|
55
68
|
end
|
@@ -60,6 +73,10 @@ module Puma
|
|
60
73
|
@mutex.synchronize { @todo.size }
|
61
74
|
end
|
62
75
|
|
76
|
+
def pool_capacity
|
77
|
+
waiting + (@max - spawned)
|
78
|
+
end
|
79
|
+
|
63
80
|
# :nodoc:
|
64
81
|
#
|
65
82
|
# Must be called with @mutex held!
|
@@ -67,7 +84,9 @@ module Puma
|
|
67
84
|
def spawn_thread
|
68
85
|
@spawned += 1
|
69
86
|
|
70
|
-
th = Thread.new do
|
87
|
+
th = Thread.new(@spawned) do |spawned|
|
88
|
+
# Thread name is new in Ruby 2.3
|
89
|
+
Thread.current.name = 'puma %03i' % spawned if Thread.current.respond_to?(:name=)
|
71
90
|
todo = @todo
|
72
91
|
block = @block
|
73
92
|
mutex = @mutex
|
@@ -112,7 +131,8 @@ module Puma
|
|
112
131
|
|
113
132
|
begin
|
114
133
|
block.call(work, *extra)
|
115
|
-
rescue Exception
|
134
|
+
rescue Exception => e
|
135
|
+
STDERR.puts "Error reached top of thread-pool: #{e.message} (#{e.class})"
|
116
136
|
end
|
117
137
|
end
|
118
138
|
|
@@ -146,9 +166,43 @@ module Puma
|
|
146
166
|
end
|
147
167
|
end
|
148
168
|
|
169
|
+
# This method is used by `Puma::Server` to let the server know when
|
170
|
+
# the thread pool can pull more requests from the socket and
|
171
|
+
# pass to the reactor.
|
172
|
+
#
|
173
|
+
# The general idea is that the thread pool can only work on a fixed
|
174
|
+
# number of requests at the same time. If it is already processing that
|
175
|
+
# number of requests then it is at capacity. If another Puma process has
|
176
|
+
# spare capacity, then the request can be left on the socket so the other
|
177
|
+
# worker can pick it up and process it.
|
178
|
+
#
|
179
|
+
# For example: if there are 5 threads, but only 4 working on
|
180
|
+
# requests, this method will not wait and the `Puma::Server`
|
181
|
+
# can pull a request right away.
|
182
|
+
#
|
183
|
+
# If there are 5 threads and all 5 of them are busy, then it will
|
184
|
+
# pause here, and wait until the `not_full` condition variable is
|
185
|
+
# signaled, usually this indicates that a request has been processed.
|
186
|
+
#
|
187
|
+
# It's important to note that even though the server might accept another
|
188
|
+
# request, it might not be added to the `@todo` array right away.
|
189
|
+
# For example if a slow client has only sent a header, but not a body
|
190
|
+
# then the `@todo` array would stay the same size as the reactor works
|
191
|
+
# to try to buffer the request. In tha scenario the next call to this
|
192
|
+
# method would not block and another request would be added into the reactor
|
193
|
+
# by the server. This would continue until a fully bufferend request
|
194
|
+
# makes it through the reactor and can then be processed by the thread pool.
|
149
195
|
def wait_until_not_full
|
150
196
|
@mutex.synchronize do
|
151
|
-
|
197
|
+
while true
|
198
|
+
return if @shutdown
|
199
|
+
|
200
|
+
# If we can still spin up new threads and there
|
201
|
+
# is work queued that cannot be handled by waiting
|
202
|
+
# threads, then accept more work until we would
|
203
|
+
# spin up the max number of threads.
|
204
|
+
return if @todo.size - @waiting < @max - @spawned
|
205
|
+
|
152
206
|
@not_full.wait @mutex
|
153
207
|
end
|
154
208
|
end
|
@@ -178,7 +232,9 @@ module Puma
|
|
178
232
|
@spawned -= 1
|
179
233
|
end
|
180
234
|
|
181
|
-
@workers
|
235
|
+
@workers.delete_if do |w|
|
236
|
+
dead_workers.include?(w)
|
237
|
+
end
|
182
238
|
end
|
183
239
|
end
|
184
240
|
|
@@ -206,7 +262,7 @@ module Puma
|
|
206
262
|
end
|
207
263
|
end
|
208
264
|
|
209
|
-
def auto_trim!(timeout=
|
265
|
+
def auto_trim!(timeout=30)
|
210
266
|
@auto_trim = AutoTrim.new(self, timeout)
|
211
267
|
@auto_trim.start!
|
212
268
|
end
|
@@ -254,18 +310,12 @@ module Puma
|
|
254
310
|
@workers.dup
|
255
311
|
end
|
256
312
|
|
257
|
-
|
258
|
-
|
313
|
+
if timeout == -1
|
314
|
+
# Wait for threads to finish without force shutdown.
|
259
315
|
threads.each(&:join)
|
260
|
-
when 0
|
261
|
-
threads.each do |t|
|
262
|
-
t.raise ForceShutdown
|
263
|
-
end
|
264
|
-
|
265
|
-
threads.each do |t|
|
266
|
-
t.join Const::SHUTDOWN_GRACE_TIME
|
267
|
-
end
|
268
316
|
else
|
317
|
+
# Wait for threads to finish after n attempts (+timeout+).
|
318
|
+
# If threads are still running, it will forcefully kill them.
|
269
319
|
timeout.times do
|
270
320
|
threads.delete_if do |t|
|
271
321
|
t.join 1
|
@@ -283,7 +333,7 @@ module Puma
|
|
283
333
|
end
|
284
334
|
|
285
335
|
threads.each do |t|
|
286
|
-
t.join
|
336
|
+
t.join SHUTDOWN_GRACE_TIME
|
287
337
|
end
|
288
338
|
end
|
289
339
|
|
data/lib/puma/util.rb
CHANGED
@@ -1,10 +1,6 @@
|
|
1
1
|
major, minor, patch = RUBY_VERSION.split('.').map { |v| v.to_i }
|
2
2
|
|
3
|
-
if major == 1 && minor <
|
4
|
-
require 'puma/rack/backports/uri/common_18'
|
5
|
-
elsif major == 1 && minor == 9 && patch == 2 && RUBY_PATCHLEVEL <= 328 && RUBY_ENGINE != 'jruby'
|
6
|
-
require 'puma/rack/backports/uri/common_192'
|
7
|
-
elsif major == 1 && minor == 9 && patch == 3 && RUBY_PATCHLEVEL < 125
|
3
|
+
if major == 1 && minor == 9 && patch == 3 && RUBY_PATCHLEVEL < 125
|
8
4
|
require 'puma/rack/backports/uri/common_193'
|
9
5
|
else
|
10
6
|
require 'uri/common'
|
data/lib/rack/handler/puma.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'rack/handler'
|
2
|
-
require 'puma'
|
3
2
|
|
4
3
|
module Rack
|
5
4
|
module Handler
|
@@ -9,38 +8,58 @@ module Rack
|
|
9
8
|
:Silent => false
|
10
9
|
}
|
11
10
|
|
12
|
-
def self.
|
13
|
-
|
11
|
+
def self.config(app, options = {})
|
12
|
+
require 'puma'
|
13
|
+
require 'puma/configuration'
|
14
|
+
require 'puma/events'
|
15
|
+
require 'puma/launcher'
|
16
|
+
|
17
|
+
default_options = DEFAULT_OPTIONS.dup
|
18
|
+
|
19
|
+
# Libraries pass in values such as :Port and there is no way to determine
|
20
|
+
# if it is a default provided by the library or a special value provided
|
21
|
+
# by the user. A special key `user_supplied_options` can be passed. This
|
22
|
+
# contains an array of all explicitly defined user options. We then
|
23
|
+
# know that all other values are defaults
|
24
|
+
if user_supplied_options = options.delete(:user_supplied_options)
|
25
|
+
(options.keys - user_supplied_options).each do |k|
|
26
|
+
default_options[k] = options.delete(k)
|
27
|
+
end
|
28
|
+
end
|
14
29
|
|
15
|
-
conf = ::Puma::Configuration.new(options) do |
|
16
|
-
|
30
|
+
conf = ::Puma::Configuration.new(options, default_options) do |user_config, file_config, default_config|
|
31
|
+
user_config.quiet
|
17
32
|
|
18
33
|
if options.delete(:Verbose)
|
19
34
|
app = Rack::CommonLogger.new(app, STDOUT)
|
20
35
|
end
|
21
36
|
|
22
37
|
if options[:environment]
|
23
|
-
|
38
|
+
user_config.environment options[:environment]
|
24
39
|
end
|
25
40
|
|
26
41
|
if options[:Threads]
|
27
42
|
min, max = options.delete(:Threads).split(':', 2)
|
28
|
-
|
43
|
+
user_config.threads min, max
|
29
44
|
end
|
30
45
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
else
|
36
|
-
host ||= ::Puma::Configuration::DefaultTCPHost
|
37
|
-
port = options[:Port] || ::Puma::Configuration::DefaultTCPPort
|
38
|
-
|
39
|
-
c.port port, host
|
46
|
+
if options[:Host] || options[:Port]
|
47
|
+
host = options[:Host] || default_options[:Host]
|
48
|
+
port = options[:Port] || default_options[:Port]
|
49
|
+
self.set_host_port_to_config(host, port, user_config)
|
40
50
|
end
|
41
51
|
|
42
|
-
|
52
|
+
self.set_host_port_to_config(default_options[:Host], default_options[:Port], default_config)
|
53
|
+
|
54
|
+
user_config.app app
|
43
55
|
end
|
56
|
+
conf
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
def self.run(app, options = {})
|
62
|
+
conf = self.config(app, options)
|
44
63
|
|
45
64
|
events = options.delete(:Silent) ? ::Puma::Events.strings : ::Puma::Events.stdio
|
46
65
|
|
@@ -64,6 +83,28 @@ module Rack
|
|
64
83
|
"Verbose" => "Don't report each request (default: false)"
|
65
84
|
}
|
66
85
|
end
|
86
|
+
private
|
87
|
+
def self.set_host_port_to_config(host, port, config)
|
88
|
+
config.clear_binds! if host || port
|
89
|
+
|
90
|
+
if host && (host[0,1] == '.' || host[0,1] == '/')
|
91
|
+
config.bind "unix://#{host}"
|
92
|
+
elsif host && host =~ /^ssl:\/\//
|
93
|
+
uri = URI.parse(host)
|
94
|
+
uri.port ||= port || ::Puma::Configuration::DefaultTCPPort
|
95
|
+
config.bind uri.to_s
|
96
|
+
else
|
97
|
+
|
98
|
+
if host
|
99
|
+
port ||= ::Puma::Configuration::DefaultTCPPort
|
100
|
+
end
|
101
|
+
|
102
|
+
if port
|
103
|
+
host ||= ::Puma::Configuration::DefaultTCPHost
|
104
|
+
config.port port, host
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
67
108
|
end
|
68
109
|
|
69
110
|
register :puma, Puma
|
data/tools/jungle/README.md
CHANGED
@@ -1,9 +1,19 @@
|
|
1
1
|
# Puma as a service
|
2
2
|
|
3
|
+
## Upstart
|
4
|
+
|
5
|
+
See `/tools/jungle/upstart` for Ubuntu's upstart scripts.
|
6
|
+
|
7
|
+
## Systemd
|
8
|
+
|
9
|
+
See [/docs/systemd](https://github.com/puma/puma/blob/master/docs/systemd.md).
|
10
|
+
|
3
11
|
## Init.d
|
4
12
|
|
13
|
+
Deprecatation Warning : `init.d` was replaced by `systemd` since Debian 8 and Ubuntu 16.04, you should look into [/docs/systemd](https://github.com/puma/puma/blob/master/docs/systemd.md) unless you are on an older OS.
|
14
|
+
|
5
15
|
See `/tools/jungle/init.d` for tools to use with init.d and start-stop-daemon.
|
6
16
|
|
7
|
-
##
|
17
|
+
## rc.d
|
8
18
|
|
9
|
-
See `/tools/jungle/
|
19
|
+
See `/tools/jungle/rc.d` for FreeBSD's rc.d scripts
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# Puma daemon service
|
2
2
|
|
3
|
+
Deprecatation Warning : `init.d` was replaced by `systemd` since Debian 8 and Ubuntu 16.04, you should look into [/docs/systemd](https://github.com/puma/puma/blob/master/docs/systemd.md) unless you are on an older OS.
|
4
|
+
|
3
5
|
Init script to manage multiple Puma servers on the same box using start-stop-daemon.
|
4
6
|
|
5
7
|
## Installation
|
@@ -22,16 +24,21 @@ Init script to manage multiple Puma servers on the same box using start-stop-dae
|
|
22
24
|
|
23
25
|
Puma apps are held in /etc/puma.conf by default. It's mainly a CSV file and every line represents one app. Here's the syntax:
|
24
26
|
|
25
|
-
app-path,user,config-file-path,log-file-path
|
27
|
+
app-path,user,config-file-path,log-file-path,environment-variables
|
26
28
|
|
27
29
|
You can add an instance by editing the file or running the following command:
|
28
30
|
|
29
31
|
sudo /etc/init.d/puma add /path/to/app user /path/to/app/config/puma.rb /path/to/app/log/puma.log
|
30
32
|
|
31
|
-
The config and log paths are optional parameters and default to:
|
33
|
+
The config and log paths, as well as the environment variables, are optional parameters and default to:
|
32
34
|
|
33
35
|
* config: /path/to/app/*config/puma.rb*
|
34
36
|
* log: /path/to/app/*log/puma.log*
|
37
|
+
* environment: (empty)
|
38
|
+
|
39
|
+
Multiple environment variables need to be separated by a semicolon, e.g.
|
40
|
+
|
41
|
+
FOO=1;BAR=2
|
35
42
|
|
36
43
|
To remove an app, simply delete the line from the config file or run:
|
37
44
|
|
data/tools/jungle/init.d/puma
CHANGED
@@ -5,9 +5,9 @@
|
|
5
5
|
# Required-Stop: $remote_fs $syslog
|
6
6
|
# Default-Start: 2 3 4 5
|
7
7
|
# Default-Stop: 0 1 6
|
8
|
-
# Short-Description:
|
9
|
-
# Description:
|
10
|
-
# placed in /etc/init.d.
|
8
|
+
# Short-Description: Puma web server
|
9
|
+
# Description: A ruby web server built for concurrency http://puma.io
|
10
|
+
# initscript to be placed in /etc/init.d.
|
11
11
|
### END INIT INFO
|
12
12
|
|
13
13
|
# Author: Darío Javier Cravero <dario@exordo.com>
|
@@ -39,17 +39,7 @@ do_start() {
|
|
39
39
|
log_daemon_msg "=> Running the jungle..."
|
40
40
|
for i in $JUNGLE; do
|
41
41
|
dir=`echo $i | cut -d , -f 1`
|
42
|
-
|
43
|
-
config_file=`echo $i | cut -d , -f 3`
|
44
|
-
if [ "$config_file" = "" ]; then
|
45
|
-
config_file="$dir/config/puma.rb"
|
46
|
-
fi
|
47
|
-
log_file=`echo $i | cut -d , -f 4`
|
48
|
-
if [ "$log_file" = "" ]; then
|
49
|
-
log_file="$dir/log/puma.log"
|
50
|
-
fi
|
51
|
-
environment=`echo $i | cut -d , -f 5`
|
52
|
-
do_start_one $dir $user $config_file $log_file $environment
|
42
|
+
do_start_one $dir
|
53
43
|
done
|
54
44
|
}
|
55
45
|
|
@@ -58,29 +48,42 @@ do_start_one() {
|
|
58
48
|
if [ -e $PIDFILE ]; then
|
59
49
|
PID=`cat $PIDFILE`
|
60
50
|
# If the puma isn't running, run it, otherwise restart it.
|
61
|
-
if
|
62
|
-
do_start_one_do $1
|
51
|
+
if ps -p $PID > /dev/null; then
|
52
|
+
do_start_one_do $1
|
63
53
|
else
|
64
54
|
do_restart_one $1
|
65
55
|
fi
|
66
56
|
else
|
67
|
-
do_start_one_do $1
|
57
|
+
do_start_one_do $1
|
68
58
|
fi
|
69
59
|
}
|
70
60
|
|
71
61
|
do_start_one_do() {
|
72
|
-
|
73
|
-
|
74
|
-
|
62
|
+
i=`grep $1 $CONFIG`
|
63
|
+
dir=`echo $i | cut -d , -f 1`
|
64
|
+
user=`echo $i | cut -d , -f 2`
|
65
|
+
config_file=`echo $i | cut -d , -f 3`
|
66
|
+
if [ "$config_file" = "" ]; then
|
67
|
+
config_file="$dir/config/puma.rb"
|
68
|
+
fi
|
69
|
+
log_file=`echo $i | cut -d , -f 4`
|
70
|
+
if [ "$log_file" = "" ]; then
|
71
|
+
log_file="$dir/log/puma.log"
|
72
|
+
fi
|
73
|
+
environment=`echo $i | cut -d , -f 5`
|
74
|
+
|
75
|
+
log_daemon_msg "--> Woke up puma $dir"
|
76
|
+
log_daemon_msg "user $user"
|
77
|
+
log_daemon_msg "log to $log_file"
|
75
78
|
|
76
|
-
if [ ! -z "$
|
77
|
-
for e in $(echo "$
|
79
|
+
if [ ! -z "$environment" ]; then
|
80
|
+
for e in $(echo "$environment" | tr ';' '\n'); do
|
78
81
|
log_daemon_msg "environment $e"
|
79
82
|
v=${e%%\=*} ; eval "$e" ; export $v
|
80
83
|
done
|
81
84
|
fi
|
82
85
|
|
83
|
-
start-stop-daemon --verbose --start --chdir $
|
86
|
+
start-stop-daemon --verbose --start --chdir $dir --chuid $user --background --exec $RUNPUMA -- $dir $config_file $log_file
|
84
87
|
}
|
85
88
|
|
86
89
|
#
|
@@ -102,7 +105,7 @@ do_stop_one() {
|
|
102
105
|
STATEFILE=$1/tmp/puma/state
|
103
106
|
if [ -e $PIDFILE ]; then
|
104
107
|
PID=`cat $PIDFILE`
|
105
|
-
if
|
108
|
+
if ps -p $PID > /dev/null; then
|
106
109
|
log_daemon_msg "---> Puma $1 isn't running."
|
107
110
|
else
|
108
111
|
log_daemon_msg "---> About to kill PID `cat $PIDFILE`"
|
@@ -135,31 +138,41 @@ do_restart() {
|
|
135
138
|
#
|
136
139
|
do_restart_one() {
|
137
140
|
PIDFILE=$1/tmp/puma/pid
|
138
|
-
|
139
|
-
dir=`echo $i | cut -d , -f 1`
|
140
|
-
|
141
|
+
|
141
142
|
if [ -e $PIDFILE ]; then
|
142
143
|
log_daemon_msg "--> About to restart puma $1"
|
143
|
-
|
144
|
-
cd $1 && bundle exec pumactl --state $dir/tmp/puma/state restart
|
145
|
-
else
|
146
|
-
pumactl --state $dir/tmp/puma/state restart
|
147
|
-
fi
|
148
|
-
# kill -s USR2 `cat $PIDFILE`
|
144
|
+
kill -s USR2 `cat $PIDFILE`
|
149
145
|
# TODO Check if process exist
|
150
146
|
else
|
151
|
-
log_daemon_msg "--> Your puma was never playing... Let's get it out there first"
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
147
|
+
log_daemon_msg "--> Your puma was never playing... Let's get it out there first"
|
148
|
+
do_start_one $1
|
149
|
+
fi
|
150
|
+
return 0
|
151
|
+
}
|
152
|
+
|
153
|
+
#
|
154
|
+
# Function that phased restarts the jungle
|
155
|
+
#
|
156
|
+
do_phased_restart() {
|
157
|
+
for i in $JUNGLE; do
|
158
|
+
dir=`echo $i | cut -d , -f 1`
|
159
|
+
do_phased_restart_one $dir
|
160
|
+
done
|
161
|
+
}
|
162
|
+
|
163
|
+
#
|
164
|
+
# Function that sends a SIGUSR1 to the daemon/service
|
165
|
+
#
|
166
|
+
do_phased_restart_one() {
|
167
|
+
PIDFILE=$1/tmp/puma/pid
|
168
|
+
|
169
|
+
if [ -e $PIDFILE ]; then
|
170
|
+
log_daemon_msg "--> About to restart puma $1"
|
171
|
+
kill -s USR1 `cat $PIDFILE`
|
172
|
+
# TODO Check if process exist
|
173
|
+
else
|
174
|
+
log_daemon_msg "--> Your puma was never playing... Let's get it out there first"
|
175
|
+
do_start_one $1
|
163
176
|
fi
|
164
177
|
return 0
|
165
178
|
}
|
@@ -256,16 +269,25 @@ do_remove() {
|
|
256
269
|
|
257
270
|
config_bundler() {
|
258
271
|
HOME="$(eval echo ~$(id -un))"
|
259
|
-
|
272
|
+
|
273
|
+
if [ -d "$1/.rbenv/bin" ]; then
|
274
|
+
PATH="$1/.rbenv/bin:$1/.rbenv/shims:$1"
|
275
|
+
eval "$(rbenv init -)"
|
276
|
+
USE_LOCAL_BUNDLE=1
|
277
|
+
return 0
|
278
|
+
|
279
|
+
elif [ -d "/usr/local/rbenv/bin" ]; then
|
260
280
|
PATH="/usr/local/rbenv/bin:/usr/local/rbenv/shims:$PATH"
|
261
281
|
eval "$(rbenv init -)"
|
262
282
|
USE_LOCAL_BUNDLE=1
|
263
283
|
return 0
|
284
|
+
|
264
285
|
elif [ -d "$HOME/.rbenv/bin" ]; then
|
265
286
|
PATH="$HOME/.rbenv/bin:$HOME/.rbenv/shims:$PATH"
|
266
287
|
eval "$(rbenv init -)"
|
267
288
|
USE_LOCAL_BUNDLE=1
|
268
289
|
return 0
|
290
|
+
|
269
291
|
# TODO: test rvm
|
270
292
|
# elif [ -f /etc/profile.d/rvm.sh ]; then
|
271
293
|
# source /etc/profile.d/rvm.sh
|
@@ -296,16 +318,7 @@ case "$1" in
|
|
296
318
|
else
|
297
319
|
i=`grep $2 $CONFIG`
|
298
320
|
dir=`echo $i | cut -d , -f 1`
|
299
|
-
|
300
|
-
config_file=`echo $i | cut -d , -f 3`
|
301
|
-
if [ "$config_file" = "" ]; then
|
302
|
-
config_file="$dir/config/puma.rb"
|
303
|
-
fi
|
304
|
-
log_file=`echo $i | cut -d , -f 4`
|
305
|
-
if [ "$log_file" = "" ]; then
|
306
|
-
log_file="$dir/log/puma.log"
|
307
|
-
fi
|
308
|
-
do_start_one $dir $user $config_file $log_file
|
321
|
+
do_start_one $dir
|
309
322
|
fi
|
310
323
|
case "$?" in
|
311
324
|
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
@@ -355,6 +368,20 @@ case "$1" in
|
|
355
368
|
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
356
369
|
esac
|
357
370
|
;;
|
371
|
+
phased-restart)
|
372
|
+
log_daemon_msg "Restarting (phased) $DESC" "$NAME"
|
373
|
+
if [ "$#" -eq 1 ]; then
|
374
|
+
do_phased_restart
|
375
|
+
else
|
376
|
+
i=`grep $2 $CONFIG`
|
377
|
+
dir=`echo $i | cut -d , -f 1`
|
378
|
+
do_phased_restart_one $dir
|
379
|
+
fi
|
380
|
+
case "$?" in
|
381
|
+
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
382
|
+
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
383
|
+
esac
|
384
|
+
;;
|
358
385
|
add)
|
359
386
|
if [ "$#" -lt 3 ]; then
|
360
387
|
echo "Please, specify the app's directory and the user that will run it at least."
|
@@ -383,11 +410,11 @@ case "$1" in
|
|
383
410
|
;;
|
384
411
|
*)
|
385
412
|
echo "Usage:" >&2
|
386
|
-
echo " Run the jungle: $SCRIPTNAME {start|stop|status|restart}" >&2
|
413
|
+
echo " Run the jungle: $SCRIPTNAME {start|stop|status|restart|phased-restart}" >&2
|
387
414
|
echo " Add a Puma: $SCRIPTNAME add /path/to/app user /path/to/app/config/puma.rb /path/to/app/config/log/puma.log"
|
388
415
|
echo " config and log are optionals."
|
389
416
|
echo " Remove a Puma: $SCRIPTNAME remove /path/to/app"
|
390
|
-
echo " On a Puma: $SCRIPTNAME {start|stop|status|restart} PUMA-NAME" >&2
|
417
|
+
echo " On a Puma: $SCRIPTNAME {start|stop|status|restart|phased-restart} PUMA-NAME" >&2
|
391
418
|
exit 3
|
392
419
|
;;
|
393
420
|
esac
|