puma 3.0.0.rc1 → 5.0.0.beta1
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} +703 -70
- data/LICENSE +23 -20
- data/README.md +173 -163
- data/docs/architecture.md +37 -0
- data/{DEPLOYMENT.md → docs/deployment.md} +28 -6
- data/docs/fork_worker.md +31 -0
- 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/jungle/README.md +13 -0
- data/docs/jungle/rc.d/README.md +74 -0
- data/docs/jungle/rc.d/puma +61 -0
- data/docs/jungle/rc.d/puma.conf +10 -0
- data/{tools → docs}/jungle/upstart/README.md +0 -0
- data/{tools → docs}/jungle/upstart/puma-manager.conf +0 -0
- data/{tools → docs}/jungle/upstart/puma.conf +1 -1
- data/docs/nginx.md +2 -2
- data/docs/plugins.md +38 -0
- data/docs/restart.md +41 -0
- data/docs/signals.md +57 -3
- data/docs/systemd.md +228 -0
- data/ext/puma_http11/PumaHttp11Service.java +2 -2
- data/ext/puma_http11/extconf.rb +16 -0
- data/ext/puma_http11/http11_parser.c +287 -468
- data/ext/puma_http11/http11_parser.h +1 -0
- data/ext/puma_http11/http11_parser.java.rl +21 -37
- data/ext/puma_http11/http11_parser.rl +10 -9
- data/ext/puma_http11/http11_parser_common.rl +4 -4
- data/ext/puma_http11/mini_ssl.c +159 -10
- data/ext/puma_http11/org/jruby/puma/Http11.java +108 -116
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +99 -132
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +30 -6
- data/ext/puma_http11/puma_http11.c +6 -38
- data/lib/puma.rb +25 -5
- data/lib/puma/accept_nonblock.rb +7 -1
- data/lib/puma/app/status.rb +53 -26
- data/lib/puma/binder.rb +150 -119
- data/lib/puma/cli.rb +56 -38
- data/lib/puma/client.rb +277 -80
- data/lib/puma/cluster.rb +326 -130
- data/lib/puma/commonlogger.rb +21 -20
- data/lib/puma/configuration.rb +160 -161
- data/lib/puma/const.rb +50 -47
- data/lib/puma/control_cli.rb +104 -63
- data/lib/puma/detect.rb +13 -1
- data/lib/puma/dsl.rb +463 -114
- data/lib/puma/events.rb +22 -13
- data/lib/puma/io_buffer.rb +9 -5
- data/lib/puma/jruby_restart.rb +2 -59
- data/lib/puma/launcher.rb +195 -105
- data/lib/puma/minissl.rb +110 -4
- data/lib/puma/minissl/context_builder.rb +76 -0
- data/lib/puma/null_io.rb +9 -14
- data/lib/puma/plugin.rb +32 -12
- data/lib/puma/plugin/tmp_restart.rb +19 -6
- data/lib/puma/rack/builder.rb +7 -5
- data/lib/puma/rack/urlmap.rb +11 -8
- data/lib/puma/rack_default.rb +2 -0
- data/lib/puma/reactor.rb +242 -32
- data/lib/puma/runner.rb +41 -30
- data/lib/puma/server.rb +265 -183
- data/lib/puma/single.rb +22 -63
- data/lib/puma/state_file.rb +9 -2
- data/lib/puma/thread_pool.rb +179 -68
- data/lib/puma/util.rb +3 -11
- data/lib/rack/handler/puma.rb +60 -11
- data/tools/Dockerfile +16 -0
- data/tools/trickletest.rb +1 -2
- metadata +35 -99
- data/COPYING +0 -55
- data/Gemfile +0 -13
- data/Manifest.txt +0 -79
- data/Rakefile +0 -158
- data/docs/config.md +0 -0
- data/ext/puma_http11/io_buffer.c +0 -155
- data/lib/puma/capistrano.rb +0 -94
- data/lib/puma/compat.rb +0 -18
- data/lib/puma/convenient.rb +0 -23
- data/lib/puma/daemon_ext.rb +0 -31
- data/lib/puma/delegation.rb +0 -11
- data/lib/puma/java_io_buffer.rb +0 -45
- data/lib/puma/rack/backports/uri/common_18.rb +0 -56
- data/lib/puma/rack/backports/uri/common_192.rb +0 -52
- data/lib/puma/rack/backports/uri/common_193.rb +0 -29
- data/lib/puma/tcp_logger.rb +0 -32
- data/puma.gemspec +0 -52
- data/tools/jungle/README.md +0 -9
- data/tools/jungle/init.d/README.md +0 -54
- data/tools/jungle/init.d/puma +0 -394
- data/tools/jungle/init.d/run-puma +0 -3
data/lib/puma/compat.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
# Provides code to work properly on 1.8 and 1.9
|
2
|
-
|
3
|
-
class String
|
4
|
-
unless method_defined? :bytesize
|
5
|
-
alias_method :bytesize, :size
|
6
|
-
end
|
7
|
-
|
8
|
-
unless method_defined? :byteslice
|
9
|
-
if RUBY_VERSION < '1.9'
|
10
|
-
alias_method :byteslice, :[]
|
11
|
-
else
|
12
|
-
def byteslice(*arg)
|
13
|
-
enc = self.encoding
|
14
|
-
self.dup.force_encoding(Encoding::ASCII_8BIT).slice(*arg).force_encoding(enc)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
data/lib/puma/convenient.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'puma/launcher'
|
2
|
-
require 'puma/configuration'
|
3
|
-
|
4
|
-
module Puma
|
5
|
-
def self.run(opts={})
|
6
|
-
cfg = Puma::Configuration.new do |c|
|
7
|
-
if port = opts[:port]
|
8
|
-
c.port port
|
9
|
-
end
|
10
|
-
|
11
|
-
c.quiet
|
12
|
-
|
13
|
-
yield c
|
14
|
-
end
|
15
|
-
|
16
|
-
cfg.clamp
|
17
|
-
|
18
|
-
events = Puma::Events.null
|
19
|
-
|
20
|
-
launcher = Puma::Launcher.new cfg, :events => events
|
21
|
-
launcher.run
|
22
|
-
end
|
23
|
-
end
|
data/lib/puma/daemon_ext.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
module Process
|
2
|
-
|
3
|
-
# This overrides the default version because it is broken if it
|
4
|
-
# exists.
|
5
|
-
|
6
|
-
if respond_to? :daemon
|
7
|
-
class << self
|
8
|
-
remove_method :daemon
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.daemon(nochdir=false, noclose=false)
|
13
|
-
exit if fork # Parent exits, child continues.
|
14
|
-
|
15
|
-
Process.setsid # Become session leader.
|
16
|
-
|
17
|
-
exit if fork # Zap session leader. See [1].
|
18
|
-
|
19
|
-
Dir.chdir "/" unless nochdir # Release old working directory.
|
20
|
-
|
21
|
-
if !noclose
|
22
|
-
STDIN.reopen File.open("/dev/null", "r")
|
23
|
-
|
24
|
-
null_out = File.open "/dev/null", "w"
|
25
|
-
STDOUT.reopen null_out
|
26
|
-
STDERR.reopen null_out
|
27
|
-
end
|
28
|
-
|
29
|
-
0
|
30
|
-
end
|
31
|
-
end
|
data/lib/puma/delegation.rb
DELETED
data/lib/puma/java_io_buffer.rb
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
require 'java'
|
2
|
-
|
3
|
-
# Conservative native JRuby/Java implementation of IOBuffer
|
4
|
-
# backed by a ByteArrayOutputStream and conversion between
|
5
|
-
# Ruby String and Java bytes
|
6
|
-
module Puma
|
7
|
-
class JavaIOBuffer < java.io.ByteArrayOutputStream
|
8
|
-
field_reader :buf
|
9
|
-
end
|
10
|
-
|
11
|
-
class IOBuffer
|
12
|
-
BUF_DEFAULT_SIZE = 4096
|
13
|
-
|
14
|
-
def initialize
|
15
|
-
@buf = JavaIOBuffer.new(BUF_DEFAULT_SIZE)
|
16
|
-
end
|
17
|
-
|
18
|
-
def reset
|
19
|
-
@buf.reset
|
20
|
-
end
|
21
|
-
|
22
|
-
def <<(str)
|
23
|
-
bytes = str.to_java_bytes
|
24
|
-
@buf.write(bytes, 0, bytes.length)
|
25
|
-
end
|
26
|
-
|
27
|
-
def append(*strs)
|
28
|
-
strs.each { |s| self << s; }
|
29
|
-
end
|
30
|
-
|
31
|
-
def to_s
|
32
|
-
String.from_java_bytes @buf.to_byte_array
|
33
|
-
end
|
34
|
-
|
35
|
-
alias_method :to_str, :to_s
|
36
|
-
|
37
|
-
def used
|
38
|
-
@buf.size
|
39
|
-
end
|
40
|
-
|
41
|
-
def capacity
|
42
|
-
@buf.buf.length
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,56 +0,0 @@
|
|
1
|
-
# :stopdoc:
|
2
|
-
|
3
|
-
# Stolen from ruby core's uri/common.rb, with modifications to support 1.8.x
|
4
|
-
#
|
5
|
-
# https://github.com/ruby/ruby/blob/trunk/lib/uri/common.rb
|
6
|
-
#
|
7
|
-
#
|
8
|
-
|
9
|
-
module URI
|
10
|
-
TBLENCWWWCOMP_ = {} # :nodoc:
|
11
|
-
256.times do |i|
|
12
|
-
TBLENCWWWCOMP_[i.chr] = '%%%02X' % i
|
13
|
-
end
|
14
|
-
TBLENCWWWCOMP_[' '] = '+'
|
15
|
-
TBLENCWWWCOMP_.freeze
|
16
|
-
TBLDECWWWCOMP_ = {} # :nodoc:
|
17
|
-
256.times do |i|
|
18
|
-
h, l = i>>4, i&15
|
19
|
-
TBLDECWWWCOMP_['%%%X%X' % [h, l]] = i.chr
|
20
|
-
TBLDECWWWCOMP_['%%%x%X' % [h, l]] = i.chr
|
21
|
-
TBLDECWWWCOMP_['%%%X%x' % [h, l]] = i.chr
|
22
|
-
TBLDECWWWCOMP_['%%%x%x' % [h, l]] = i.chr
|
23
|
-
end
|
24
|
-
TBLDECWWWCOMP_['+'] = ' '
|
25
|
-
TBLDECWWWCOMP_.freeze
|
26
|
-
|
27
|
-
# Encode given +s+ to URL-encoded form data.
|
28
|
-
#
|
29
|
-
# This method doesn't convert *, -, ., 0-9, A-Z, _, a-z, but does convert SP
|
30
|
-
# (ASCII space) to + and converts others to %XX.
|
31
|
-
#
|
32
|
-
# This is an implementation of
|
33
|
-
# http://www.w3.org/TR/html5/forms.html#url-encoded-form-data
|
34
|
-
#
|
35
|
-
# See URI.decode_www_form_component, URI.encode_www_form
|
36
|
-
def self.encode_www_form_component(s)
|
37
|
-
str = s.to_s
|
38
|
-
if RUBY_VERSION < "1.9" && $KCODE =~ /u/i
|
39
|
-
str.gsub(/([^ a-zA-Z0-9_.-]+)/) do
|
40
|
-
'%' + $1.unpack('H2' * Rack::Utils.bytesize($1)).join('%').upcase
|
41
|
-
end.tr(' ', '+')
|
42
|
-
else
|
43
|
-
str.gsub(/[^*\-.0-9A-Z_a-z]/) {|m| TBLENCWWWCOMP_[m]}
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# Decode given +str+ of URL-encoded form data.
|
48
|
-
#
|
49
|
-
# This decodes + to SP.
|
50
|
-
#
|
51
|
-
# See URI.encode_www_form_component, URI.decode_www_form
|
52
|
-
def self.decode_www_form_component(str, enc=nil)
|
53
|
-
raise ArgumentError, "invalid %-encoding (#{str})" unless /\A(?:%[0-9a-fA-F]{2}|[^%])*\z/ =~ str
|
54
|
-
str.gsub(/\+|%[0-9a-fA-F]{2}/) {|m| TBLDECWWWCOMP_[m]}
|
55
|
-
end
|
56
|
-
end
|
@@ -1,52 +0,0 @@
|
|
1
|
-
# :stopdoc:
|
2
|
-
|
3
|
-
# Stolen from ruby core's uri/common.rb @32618ba to fix DoS issues in 1.9.2
|
4
|
-
#
|
5
|
-
# https://github.com/ruby/ruby/blob/32618ba7438a2247042bba9b5d85b5d49070f5e5/lib/uri/common.rb
|
6
|
-
#
|
7
|
-
# Issue:
|
8
|
-
# http://redmine.ruby-lang.org/issues/5149
|
9
|
-
#
|
10
|
-
# Relevant Fixes:
|
11
|
-
# https://github.com/ruby/ruby/commit/b5f91deee04aa6ccbe07c23c8222b937c22a799b
|
12
|
-
# https://github.com/ruby/ruby/commit/93177c1e5c3906abf14472ae0b905d8b5c72ce1b
|
13
|
-
#
|
14
|
-
# This should probably be removed once there is a Ruby 1.9.2 patch level that
|
15
|
-
# includes this fix.
|
16
|
-
|
17
|
-
require 'uri/common'
|
18
|
-
|
19
|
-
module URI
|
20
|
-
TBLDECWWWCOMP_ = {} unless const_defined?(:TBLDECWWWCOMP_) #:nodoc:
|
21
|
-
if TBLDECWWWCOMP_.empty?
|
22
|
-
256.times do |i|
|
23
|
-
h, l = i>>4, i&15
|
24
|
-
TBLDECWWWCOMP_['%%%X%X' % [h, l]] = i.chr
|
25
|
-
TBLDECWWWCOMP_['%%%x%X' % [h, l]] = i.chr
|
26
|
-
TBLDECWWWCOMP_['%%%X%x' % [h, l]] = i.chr
|
27
|
-
TBLDECWWWCOMP_['%%%x%x' % [h, l]] = i.chr
|
28
|
-
end
|
29
|
-
TBLDECWWWCOMP_['+'] = ' '
|
30
|
-
TBLDECWWWCOMP_.freeze
|
31
|
-
end
|
32
|
-
|
33
|
-
def self.decode_www_form(str, enc=Encoding::UTF_8)
|
34
|
-
return [] if str.empty?
|
35
|
-
unless /\A#{WFKV_}=#{WFKV_}(?:[;&]#{WFKV_}=#{WFKV_})*\z/o =~ str
|
36
|
-
raise ArgumentError, "invalid data of application/x-www-form-urlencoded (#{str})"
|
37
|
-
end
|
38
|
-
ary = []
|
39
|
-
$&.scan(/([^=;&]+)=([^;&]*)/) do
|
40
|
-
ary << [decode_www_form_component($1, enc), decode_www_form_component($2, enc)]
|
41
|
-
end
|
42
|
-
ary
|
43
|
-
end
|
44
|
-
|
45
|
-
def self.decode_www_form_component(str, enc=Encoding::UTF_8)
|
46
|
-
raise ArgumentError, "invalid %-encoding (#{str})" unless /\A[^%]*(?:%\h\h[^%]*)*\z/ =~ str
|
47
|
-
str.gsub(/\+|%\h\h/, TBLDECWWWCOMP_).force_encoding(enc)
|
48
|
-
end
|
49
|
-
|
50
|
-
remove_const :WFKV_ if const_defined?(:WFKV_)
|
51
|
-
WFKV_ = '(?:[^%#=;&]*(?:%\h\h[^%#=;&]*)*)' # :nodoc:
|
52
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
# :stopdoc:
|
2
|
-
|
3
|
-
require 'uri/common'
|
4
|
-
|
5
|
-
# Issue:
|
6
|
-
# http://bugs.ruby-lang.org/issues/5925
|
7
|
-
#
|
8
|
-
# Relevant commit:
|
9
|
-
# https://github.com/ruby/ruby/commit/edb7cdf1eabaff78dfa5ffedfbc2e91b29fa9ca1
|
10
|
-
|
11
|
-
module URI
|
12
|
-
256.times do |i|
|
13
|
-
TBLENCWWWCOMP_[i.chr] = '%%%02X' % i
|
14
|
-
end
|
15
|
-
TBLENCWWWCOMP_[' '] = '+'
|
16
|
-
TBLENCWWWCOMP_.freeze
|
17
|
-
|
18
|
-
256.times do |i|
|
19
|
-
h, l = i>>4, i&15
|
20
|
-
TBLDECWWWCOMP_['%%%X%X' % [h, l]] = i.chr
|
21
|
-
TBLDECWWWCOMP_['%%%x%X' % [h, l]] = i.chr
|
22
|
-
TBLDECWWWCOMP_['%%%X%x' % [h, l]] = i.chr
|
23
|
-
TBLDECWWWCOMP_['%%%x%x' % [h, l]] = i.chr
|
24
|
-
end
|
25
|
-
TBLDECWWWCOMP_['+'] = ' '
|
26
|
-
TBLDECWWWCOMP_.freeze
|
27
|
-
end
|
28
|
-
|
29
|
-
# :startdoc:
|
data/lib/puma/tcp_logger.rb
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
module Puma
|
2
|
-
class TCPLogger
|
3
|
-
def initialize(logger, app, quiet=false)
|
4
|
-
@logger = logger
|
5
|
-
@app = app
|
6
|
-
@quiet = quiet
|
7
|
-
end
|
8
|
-
|
9
|
-
FORMAT = "%s - %s"
|
10
|
-
|
11
|
-
def log(who, str)
|
12
|
-
now = Time.now.strftime("%d/%b/%Y %H:%M:%S")
|
13
|
-
|
14
|
-
@logger.puts "#{now} - #{who} - #{str}"
|
15
|
-
end
|
16
|
-
|
17
|
-
def call(env, socket)
|
18
|
-
who = env[Const::REMOTE_ADDR]
|
19
|
-
log who, "connected" unless @quiet
|
20
|
-
|
21
|
-
env['log'] = lambda { |str| log(who, str) }
|
22
|
-
|
23
|
-
begin
|
24
|
-
@app.call env, socket
|
25
|
-
rescue Object => e
|
26
|
-
log who, "exception: #{e.message} (#{e.class})"
|
27
|
-
else
|
28
|
-
log who, "disconnected" unless @quiet
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
data/puma.gemspec
DELETED
@@ -1,52 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
|
3
|
-
# This is only used when puma is a git dep from Bundler, so it's a little
|
4
|
-
# weird.
|
5
|
-
|
6
|
-
d = File.read(File.expand_path("../lib/puma/const.rb", __FILE__))
|
7
|
-
if d =~ /VERSION = "(\d+\.\d+\.\d+)"/
|
8
|
-
version = $1
|
9
|
-
else
|
10
|
-
version = "0.0.1"
|
11
|
-
end
|
12
|
-
|
13
|
-
Gem::Specification.new do |s|
|
14
|
-
s.name = "puma"
|
15
|
-
s.version = version
|
16
|
-
|
17
|
-
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
18
|
-
s.authors = ["Evan Phoenix"]
|
19
|
-
s.date = `git log --pretty="%ai" -n 1`.split(" ").first
|
20
|
-
s.description = "Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications. Puma is intended for use in both development and production environments. In order to get the best throughput, it is highly recommended that you use a Ruby implementation with real threads like Rubinius or JRuby."
|
21
|
-
s.email = ["evan@phx.io"]
|
22
|
-
s.executables = ["puma", "pumactl"]
|
23
|
-
s.extensions = ["ext/puma_http11/extconf.rb"]
|
24
|
-
s.files = `git ls-files`.split($/)
|
25
|
-
s.homepage = "http://puma.io"
|
26
|
-
s.license = "BSD-3-Clause"
|
27
|
-
s.rdoc_options = ["--main", "README.md"]
|
28
|
-
s.require_paths = ["lib"]
|
29
|
-
s.required_ruby_version = Gem::Requirement.new(">= 1.8.7")
|
30
|
-
s.rubyforge_project = "puma"
|
31
|
-
s.rubygems_version = "1.8.25"
|
32
|
-
s.summary = "Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications"
|
33
|
-
s.test_files = s.files.grep(/^test/)
|
34
|
-
|
35
|
-
if s.respond_to? :specification_version then
|
36
|
-
s.specification_version = 3
|
37
|
-
|
38
|
-
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
39
|
-
s.add_development_dependency(%q<rdoc>, ["~> 4.0"])
|
40
|
-
s.add_development_dependency(%q<rake-compiler>, ["~> 0.8.0"])
|
41
|
-
s.add_development_dependency(%q<hoe>, ["~> 3.6"])
|
42
|
-
else
|
43
|
-
s.add_dependency(%q<rdoc>, ["~> 4.0"])
|
44
|
-
s.add_dependency(%q<rake-compiler>, ["~> 0.8.0"])
|
45
|
-
s.add_dependency(%q<hoe>, ["~> 3.6"])
|
46
|
-
end
|
47
|
-
else
|
48
|
-
s.add_dependency(%q<rdoc>, ["~> 4.0"])
|
49
|
-
s.add_dependency(%q<rake-compiler>, ["~> 0.8.0"])
|
50
|
-
s.add_dependency(%q<hoe>, ["~> 3.6"])
|
51
|
-
end
|
52
|
-
end
|
data/tools/jungle/README.md
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
# Puma daemon service
|
2
|
-
|
3
|
-
Init script to manage multiple Puma servers on the same box using start-stop-daemon.
|
4
|
-
|
5
|
-
## Installation
|
6
|
-
|
7
|
-
# Copy the init script to services directory
|
8
|
-
sudo cp puma /etc/init.d
|
9
|
-
sudo chmod +x /etc/init.d/puma
|
10
|
-
|
11
|
-
# Make it start at boot time.
|
12
|
-
sudo update-rc.d -f puma defaults
|
13
|
-
|
14
|
-
# Copy the Puma runner to an accessible location
|
15
|
-
sudo cp run-puma /usr/local/bin
|
16
|
-
sudo chmod +x /usr/local/bin/run-puma
|
17
|
-
|
18
|
-
# Create an empty configuration file
|
19
|
-
sudo touch /etc/puma.conf
|
20
|
-
|
21
|
-
## Managing the jungle
|
22
|
-
|
23
|
-
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
|
-
|
25
|
-
app-path,user,config-file-path,log-file-path
|
26
|
-
|
27
|
-
You can add an instance by editing the file or running the following command:
|
28
|
-
|
29
|
-
sudo /etc/init.d/puma add /path/to/app user /path/to/app/config/puma.rb /path/to/app/log/puma.log
|
30
|
-
|
31
|
-
The config and log paths are optional parameters and default to:
|
32
|
-
|
33
|
-
* config: /path/to/app/*config/puma.rb*
|
34
|
-
* log: /path/to/app/*log/puma.log*
|
35
|
-
|
36
|
-
To remove an app, simply delete the line from the config file or run:
|
37
|
-
|
38
|
-
sudo /etc/init.d/puma remove /path/to/app
|
39
|
-
|
40
|
-
The command will make sure the Puma instance stops before removing it from the jungle.
|
41
|
-
|
42
|
-
## Assumptions
|
43
|
-
|
44
|
-
* The script expects a temporary folder named /path/to/app/*tmp/puma* to exist. Create it if it's not there by default.
|
45
|
-
The pid and state files should live there and must be called: *tmp/puma/pid* and *tmp/puma/state*.
|
46
|
-
You can change those if you want but you'll have to adapt the script for it to work.
|
47
|
-
|
48
|
-
* Here's what a minimal app's config file should have:
|
49
|
-
|
50
|
-
```
|
51
|
-
pidfile "/path/to/app/tmp/puma/pid"
|
52
|
-
state_path "/path/to/app/tmp/puma/state"
|
53
|
-
activate_control_app
|
54
|
-
```
|
data/tools/jungle/init.d/puma
DELETED
@@ -1,394 +0,0 @@
|
|
1
|
-
#! /bin/sh
|
2
|
-
### BEGIN INIT INFO
|
3
|
-
# Provides: puma
|
4
|
-
# Required-Start: $remote_fs $syslog
|
5
|
-
# Required-Stop: $remote_fs $syslog
|
6
|
-
# Default-Start: 2 3 4 5
|
7
|
-
# Default-Stop: 0 1 6
|
8
|
-
# Short-Description: Example initscript
|
9
|
-
# Description: This file should be used to construct scripts to be
|
10
|
-
# placed in /etc/init.d.
|
11
|
-
### END INIT INFO
|
12
|
-
|
13
|
-
# Author: Darío Javier Cravero <dario@exordo.com>
|
14
|
-
#
|
15
|
-
# Do NOT "set -e"
|
16
|
-
|
17
|
-
# PATH should only include /usr/* if it runs after the mountnfs.sh script
|
18
|
-
PATH=/usr/local/bin:/usr/local/sbin/:/sbin:/usr/sbin:/bin:/usr/bin
|
19
|
-
DESC="Puma rack web server"
|
20
|
-
NAME=puma
|
21
|
-
DAEMON=$NAME
|
22
|
-
SCRIPTNAME=/etc/init.d/$NAME
|
23
|
-
CONFIG=/etc/puma.conf
|
24
|
-
JUNGLE=`cat $CONFIG`
|
25
|
-
RUNPUMA=/usr/local/bin/run-puma
|
26
|
-
USE_LOCAL_BUNDLE=0
|
27
|
-
|
28
|
-
# Load the VERBOSE setting and other rcS variables
|
29
|
-
. /lib/init/vars.sh
|
30
|
-
|
31
|
-
# Define LSB log_* functions.
|
32
|
-
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
|
33
|
-
. /lib/lsb/init-functions
|
34
|
-
|
35
|
-
#
|
36
|
-
# Function that starts the jungle
|
37
|
-
#
|
38
|
-
do_start() {
|
39
|
-
log_daemon_msg "=> Running the jungle..."
|
40
|
-
for i in $JUNGLE; do
|
41
|
-
dir=`echo $i | cut -d , -f 1`
|
42
|
-
user=`echo $i | cut -d , -f 2`
|
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
|
53
|
-
done
|
54
|
-
}
|
55
|
-
|
56
|
-
do_start_one() {
|
57
|
-
PIDFILE=$1/tmp/puma/pid
|
58
|
-
if [ -e $PIDFILE ]; then
|
59
|
-
PID=`cat $PIDFILE`
|
60
|
-
# If the puma isn't running, run it, otherwise restart it.
|
61
|
-
if [ "`ps -A -o pid= | grep -c $PID`" -eq 0 ]; then
|
62
|
-
do_start_one_do $1 $2 $3 $4 $5
|
63
|
-
else
|
64
|
-
do_restart_one $1
|
65
|
-
fi
|
66
|
-
else
|
67
|
-
do_start_one_do $1 $2 $3 $4 $5
|
68
|
-
fi
|
69
|
-
}
|
70
|
-
|
71
|
-
do_start_one_do() {
|
72
|
-
log_daemon_msg "--> Woke up puma $1"
|
73
|
-
log_daemon_msg "user $2"
|
74
|
-
log_daemon_msg "log to $4"
|
75
|
-
|
76
|
-
if [ ! -z "$5" ]; then
|
77
|
-
for e in $(echo "$5" | tr ';' '\n'); do
|
78
|
-
log_daemon_msg "environment $e"
|
79
|
-
v=${e%%\=*} ; eval "$e" ; export $v
|
80
|
-
done
|
81
|
-
fi
|
82
|
-
|
83
|
-
start-stop-daemon --verbose --start --chdir $1 --chuid $2 --background --exec $RUNPUMA -- $1 $3 $4
|
84
|
-
}
|
85
|
-
|
86
|
-
#
|
87
|
-
# Function that stops the jungle
|
88
|
-
#
|
89
|
-
do_stop() {
|
90
|
-
log_daemon_msg "=> Putting all the beasts to bed..."
|
91
|
-
for i in $JUNGLE; do
|
92
|
-
dir=`echo $i | cut -d , -f 1`
|
93
|
-
do_stop_one $dir
|
94
|
-
done
|
95
|
-
}
|
96
|
-
#
|
97
|
-
# Function that stops the daemon/service
|
98
|
-
#
|
99
|
-
do_stop_one() {
|
100
|
-
log_daemon_msg "--> Stopping $1"
|
101
|
-
PIDFILE=$1/tmp/puma/pid
|
102
|
-
STATEFILE=$1/tmp/puma/state
|
103
|
-
if [ -e $PIDFILE ]; then
|
104
|
-
PID=`cat $PIDFILE`
|
105
|
-
if [ "`ps -A -o pid= | grep -c $PID`" -eq 0 ]; then
|
106
|
-
log_daemon_msg "---> Puma $1 isn't running."
|
107
|
-
else
|
108
|
-
log_daemon_msg "---> About to kill PID `cat $PIDFILE`"
|
109
|
-
if [ "$USE_LOCAL_BUNDLE" -eq 1 ]; then
|
110
|
-
cd $1 && bundle exec pumactl --state $STATEFILE stop
|
111
|
-
else
|
112
|
-
pumactl --state $STATEFILE stop
|
113
|
-
fi
|
114
|
-
# Many daemons don't delete their pidfiles when they exit.
|
115
|
-
rm -f $PIDFILE $STATEFILE
|
116
|
-
fi
|
117
|
-
else
|
118
|
-
log_daemon_msg "---> No puma here..."
|
119
|
-
fi
|
120
|
-
return 0
|
121
|
-
}
|
122
|
-
|
123
|
-
#
|
124
|
-
# Function that restarts the jungle
|
125
|
-
#
|
126
|
-
do_restart() {
|
127
|
-
for i in $JUNGLE; do
|
128
|
-
dir=`echo $i | cut -d , -f 1`
|
129
|
-
do_restart_one $dir
|
130
|
-
done
|
131
|
-
}
|
132
|
-
|
133
|
-
#
|
134
|
-
# Function that sends a SIGUSR2 to the daemon/service
|
135
|
-
#
|
136
|
-
do_restart_one() {
|
137
|
-
PIDFILE=$1/tmp/puma/pid
|
138
|
-
i=`grep $1 $CONFIG`
|
139
|
-
dir=`echo $i | cut -d , -f 1`
|
140
|
-
|
141
|
-
if [ -e $PIDFILE ]; then
|
142
|
-
log_daemon_msg "--> About to restart puma $1"
|
143
|
-
if [ "$USE_LOCAL_BUNDLE" -eq 1 ]; then
|
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`
|
149
|
-
# TODO Check if process exist
|
150
|
-
else
|
151
|
-
log_daemon_msg "--> Your puma was never playing... Let's get it out there first"
|
152
|
-
user=`echo $i | cut -d , -f 2`
|
153
|
-
config_file=`echo $i | cut -d , -f 3`
|
154
|
-
if [ "$config_file" = "" ]; then
|
155
|
-
config_file="$dir/config/puma.rb"
|
156
|
-
fi
|
157
|
-
log_file=`echo $i | cut -d , -f 4`
|
158
|
-
if [ "$log_file" = "" ]; then
|
159
|
-
log_file="$dir/log/puma.log"
|
160
|
-
fi
|
161
|
-
environment=`echo $i | cut -d , -f 5`
|
162
|
-
do_start_one $dir $user $config_file $log_file $environment
|
163
|
-
fi
|
164
|
-
return 0
|
165
|
-
}
|
166
|
-
|
167
|
-
#
|
168
|
-
# Function that statuss the jungle
|
169
|
-
#
|
170
|
-
do_status() {
|
171
|
-
for i in $JUNGLE; do
|
172
|
-
dir=`echo $i | cut -d , -f 1`
|
173
|
-
do_status_one $dir
|
174
|
-
done
|
175
|
-
}
|
176
|
-
|
177
|
-
#
|
178
|
-
# Function that sends a SIGUSR2 to the daemon/service
|
179
|
-
#
|
180
|
-
do_status_one() {
|
181
|
-
PIDFILE=$1/tmp/puma/pid
|
182
|
-
i=`grep $1 $CONFIG`
|
183
|
-
dir=`echo $i | cut -d , -f 1`
|
184
|
-
|
185
|
-
if [ -e $PIDFILE ]; then
|
186
|
-
log_daemon_msg "--> About to status puma $1"
|
187
|
-
if [ "$USE_LOCAL_BUNDLE" -eq 1 ]; then
|
188
|
-
cd $1 && bundle exec pumactl --state $dir/tmp/puma/state stats
|
189
|
-
else
|
190
|
-
pumactl --state $dir/tmp/puma/state stats
|
191
|
-
fi
|
192
|
-
# kill -s USR2 `cat $PIDFILE`
|
193
|
-
# TODO Check if process exist
|
194
|
-
else
|
195
|
-
log_daemon_msg "--> $1 isn't there :(..."
|
196
|
-
fi
|
197
|
-
return 0
|
198
|
-
}
|
199
|
-
|
200
|
-
do_add() {
|
201
|
-
str=""
|
202
|
-
# App's directory
|
203
|
-
if [ -d "$1" ]; then
|
204
|
-
if [ "`grep -c "^$1" $CONFIG`" -eq 0 ]; then
|
205
|
-
str=$1
|
206
|
-
else
|
207
|
-
echo "The app is already being managed. Remove it if you want to update its config."
|
208
|
-
exit 1
|
209
|
-
fi
|
210
|
-
else
|
211
|
-
echo "The directory $1 doesn't exist."
|
212
|
-
exit 1
|
213
|
-
fi
|
214
|
-
# User to run it as
|
215
|
-
if [ "`grep -c "^$2:" /etc/passwd`" -eq 0 ]; then
|
216
|
-
echo "The user $2 doesn't exist."
|
217
|
-
exit 1
|
218
|
-
else
|
219
|
-
str="$str,$2"
|
220
|
-
fi
|
221
|
-
# Config file
|
222
|
-
if [ "$3" != "" ]; then
|
223
|
-
if [ -e $3 ]; then
|
224
|
-
str="$str,$3"
|
225
|
-
else
|
226
|
-
echo "The config file $3 doesn't exist."
|
227
|
-
exit 1
|
228
|
-
fi
|
229
|
-
fi
|
230
|
-
# Log file
|
231
|
-
if [ "$4" != "" ]; then
|
232
|
-
str="$str,$4"
|
233
|
-
fi
|
234
|
-
|
235
|
-
# Environment variables
|
236
|
-
if [ "$5" != "" ]; then
|
237
|
-
str="$str,$5"
|
238
|
-
fi
|
239
|
-
|
240
|
-
# Add it to the jungle
|
241
|
-
echo $str >> $CONFIG
|
242
|
-
log_daemon_msg "Added a Puma to the jungle: $str. You still have to start it though."
|
243
|
-
}
|
244
|
-
|
245
|
-
do_remove() {
|
246
|
-
if [ "`grep -c "^$1" $CONFIG`" -eq 0 ]; then
|
247
|
-
echo "There's no app $1 to remove."
|
248
|
-
else
|
249
|
-
# Stop it first.
|
250
|
-
do_stop_one $1
|
251
|
-
# Remove it from the config.
|
252
|
-
sed -i "\\:^$1:d" $CONFIG
|
253
|
-
log_daemon_msg "Removed a Puma from the jungle: $1."
|
254
|
-
fi
|
255
|
-
}
|
256
|
-
|
257
|
-
config_bundler() {
|
258
|
-
HOME="$(eval echo ~$(id -un))"
|
259
|
-
if [ -d "/usr/local/rbenv/bin" ]; then
|
260
|
-
PATH="/usr/local/rbenv/bin:/usr/local/rbenv/shims:$PATH"
|
261
|
-
eval "$(rbenv init -)"
|
262
|
-
USE_LOCAL_BUNDLE=1
|
263
|
-
return 0
|
264
|
-
elif [ -d "$HOME/.rbenv/bin" ]; then
|
265
|
-
PATH="$HOME/.rbenv/bin:$HOME/.rbenv/shims:$PATH"
|
266
|
-
eval "$(rbenv init -)"
|
267
|
-
USE_LOCAL_BUNDLE=1
|
268
|
-
return 0
|
269
|
-
# TODO: test rvm
|
270
|
-
# elif [ -f /etc/profile.d/rvm.sh ]; then
|
271
|
-
# source /etc/profile.d/rvm.sh
|
272
|
-
# elif [ -f /usr/local/rvm/scripts/rvm ]; then
|
273
|
-
# source /etc/profile.d/rvm.sh
|
274
|
-
# elif [ -f "$HOME/.rvm/scripts/rvm" ]; then
|
275
|
-
# source "$HOME/.rvm/scripts/rvm"
|
276
|
-
# TODO: don't know what to do with chruby
|
277
|
-
# elif [ -f /usr/local/share/chruby/chruby.sh ]; then
|
278
|
-
# source /usr/local/share/chruby/chruby.sh
|
279
|
-
# if [ -f /usr/local/share/chruby/auto.sh ]; then
|
280
|
-
# source /usr/local/share/chruby/auto.sh
|
281
|
-
# fi
|
282
|
-
# if you aren't using auto, set your version here
|
283
|
-
# chruby 2.0.0
|
284
|
-
fi
|
285
|
-
|
286
|
-
return 1
|
287
|
-
}
|
288
|
-
|
289
|
-
config_bundler
|
290
|
-
|
291
|
-
case "$1" in
|
292
|
-
start)
|
293
|
-
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
|
294
|
-
if [ "$#" -eq 1 ]; then
|
295
|
-
do_start
|
296
|
-
else
|
297
|
-
i=`grep $2 $CONFIG`
|
298
|
-
dir=`echo $i | cut -d , -f 1`
|
299
|
-
user=`echo $i | cut -d , -f 2`
|
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
|
309
|
-
fi
|
310
|
-
case "$?" in
|
311
|
-
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
312
|
-
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
313
|
-
esac
|
314
|
-
;;
|
315
|
-
stop)
|
316
|
-
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
|
317
|
-
if [ "$#" -eq 1 ]; then
|
318
|
-
do_stop
|
319
|
-
else
|
320
|
-
i=`grep $2 $CONFIG`
|
321
|
-
dir=`echo $i | cut -d , -f 1`
|
322
|
-
do_stop_one $dir
|
323
|
-
fi
|
324
|
-
case "$?" in
|
325
|
-
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
326
|
-
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
327
|
-
esac
|
328
|
-
;;
|
329
|
-
status)
|
330
|
-
# TODO Implement.
|
331
|
-
log_daemon_msg "Status $DESC" "$NAME"
|
332
|
-
if [ "$#" -eq 1 ]; then
|
333
|
-
do_status
|
334
|
-
else
|
335
|
-
i=`grep $2 $CONFIG`
|
336
|
-
dir=`echo $i | cut -d , -f 1`
|
337
|
-
do_status_one $dir
|
338
|
-
fi
|
339
|
-
case "$?" in
|
340
|
-
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
341
|
-
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
342
|
-
esac
|
343
|
-
;;
|
344
|
-
restart)
|
345
|
-
log_daemon_msg "Restarting $DESC" "$NAME"
|
346
|
-
if [ "$#" -eq 1 ]; then
|
347
|
-
do_restart
|
348
|
-
else
|
349
|
-
i=`grep $2 $CONFIG`
|
350
|
-
dir=`echo $i | cut -d , -f 1`
|
351
|
-
do_restart_one $dir
|
352
|
-
fi
|
353
|
-
case "$?" in
|
354
|
-
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
355
|
-
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
356
|
-
esac
|
357
|
-
;;
|
358
|
-
add)
|
359
|
-
if [ "$#" -lt 3 ]; then
|
360
|
-
echo "Please, specifiy the app's directory and the user that will run it at least."
|
361
|
-
echo " Usage: $SCRIPTNAME add /path/to/app user /path/to/app/config/puma.rb /path/to/app/config/log/puma.log"
|
362
|
-
echo " config and log are optionals."
|
363
|
-
exit 1
|
364
|
-
else
|
365
|
-
do_add $2 $3 $4 $5
|
366
|
-
fi
|
367
|
-
case "$?" in
|
368
|
-
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
369
|
-
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
370
|
-
esac
|
371
|
-
;;
|
372
|
-
remove)
|
373
|
-
if [ "$#" -lt 2 ]; then
|
374
|
-
echo "Please, specifiy the app's directory to remove."
|
375
|
-
exit 1
|
376
|
-
else
|
377
|
-
do_remove $2
|
378
|
-
fi
|
379
|
-
case "$?" in
|
380
|
-
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
381
|
-
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
382
|
-
esac
|
383
|
-
;;
|
384
|
-
*)
|
385
|
-
echo "Usage:" >&2
|
386
|
-
echo " Run the jungle: $SCRIPTNAME {start|stop|status|restart}" >&2
|
387
|
-
echo " Add a Puma: $SCRIPTNAME add /path/to/app user /path/to/app/config/puma.rb /path/to/app/config/log/puma.log"
|
388
|
-
echo " config and log are optionals."
|
389
|
-
echo " Remove a Puma: $SCRIPTNAME remove /path/to/app"
|
390
|
-
echo " On a Puma: $SCRIPTNAME {start|stop|status|restart} PUMA-NAME" >&2
|
391
|
-
exit 3
|
392
|
-
;;
|
393
|
-
esac
|
394
|
-
:
|