puma 1.6.3 → 2.0.0.b1
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.
- data/History.txt +13 -0
- data/Manifest.txt +18 -0
- data/Rakefile +6 -0
- data/docs/config.md +0 -0
- data/docs/nginx.md +85 -0
- data/examples/puma/keystore.jks +0 -0
- data/ext/puma_http11/PumaHttp11Service.java +2 -0
- data/ext/puma_http11/extconf.rb +3 -0
- data/ext/puma_http11/io_buffer.c +146 -0
- data/ext/puma_http11/mini_ssl.c +189 -0
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +289 -0
- data/ext/puma_http11/puma_http11.c +6 -0
- data/lib/puma/accept_nonblock.rb +23 -0
- data/lib/puma/binder.rb +253 -0
- data/lib/puma/cli.rb +212 -114
- data/lib/puma/client.rb +28 -3
- data/lib/puma/configuration.rb +11 -4
- data/lib/puma/const.rb +12 -1
- data/lib/puma/delegation.rb +11 -0
- data/lib/puma/events.rb +18 -0
- data/lib/puma/io_buffer.rb +7 -0
- data/lib/puma/java_io_buffer.rb +45 -0
- data/lib/puma/minissl.rb +124 -0
- data/lib/puma/puma_http11.bundle +0 -0
- data/lib/puma/puma_http11.jar +0 -0
- data/lib/puma/reactor.rb +4 -1
- data/lib/puma/server.rb +67 -144
- data/lib/puma/thread_pool.rb +5 -2
- data/puma.gemspec +5 -5
- data/test/test_integration.rb +53 -2
- data/test/test_iobuffer.rb +38 -0
- data/test/test_puma_server.rb +12 -7
- data/tools/jungle/README.md +54 -0
- data/tools/jungle/puma +332 -0
- data/tools/jungle/run-puma +3 -0
- metadata +24 -5
data/lib/puma/thread_pool.rb
CHANGED
@@ -11,7 +11,7 @@ module Puma
|
|
11
11
|
# The block passed is the work that will be performed in each
|
12
12
|
# thread.
|
13
13
|
#
|
14
|
-
def initialize(min, max, &blk)
|
14
|
+
def initialize(min, max, *extra, &blk)
|
15
15
|
@cond = ConditionVariable.new
|
16
16
|
@mutex = Mutex.new
|
17
17
|
|
@@ -23,6 +23,7 @@ module Puma
|
|
23
23
|
@min = min
|
24
24
|
@max = max
|
25
25
|
@block = blk
|
26
|
+
@extra = extra
|
26
27
|
|
27
28
|
@shutdown = false
|
28
29
|
|
@@ -58,6 +59,8 @@ module Puma
|
|
58
59
|
mutex = @mutex
|
59
60
|
cond = @cond
|
60
61
|
|
62
|
+
extra = @extra.map { |i| i.new }
|
63
|
+
|
61
64
|
while true
|
62
65
|
work = nil
|
63
66
|
|
@@ -91,7 +94,7 @@ module Puma
|
|
91
94
|
|
92
95
|
break unless continue
|
93
96
|
|
94
|
-
block.call
|
97
|
+
block.call(work, *extra)
|
95
98
|
end
|
96
99
|
|
97
100
|
mutex.synchronize do
|
data/puma.gemspec
CHANGED
@@ -2,17 +2,17 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "puma"
|
5
|
-
s.version = "
|
5
|
+
s.version = "2.0.0.b1"
|
6
6
|
|
7
|
-
s.required_rubygems_version = Gem::Requirement.new("
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Evan Phoenix"]
|
9
|
-
s.date = "2012-09-
|
9
|
+
s.date = "2012-09-12"
|
10
10
|
s.description = "Puma is a simple, fast, and highly concurrent HTTP 1.1 server for Ruby web applications. It can be used with any application that supports Rack, and is considered the replacement for Webrick and Mongrel. It was designed to be the go-to server for [Rubinius](http://rubini.us), but also works well with JRuby and MRI. Puma is intended for use in both development and production environments.\n\nUnder the hood, Puma processes requests using a C-optimized Ragel extension (inherited from Mongrel) that provides fast, accurate HTTP 1.1 protocol parsing in a portable way. Puma then serves the request in a thread from an internal thread pool (which you can control). This allows Puma to provide real concurrency for your web application!\n\nWith Rubinius 2.0, Puma will utilize all cores on your CPU with real threads, meaning you won't have to spawn multiple processes to increase throughput. You can expect to see a similar benefit from JRuby.\n\nOn MRI, there is a Global Interpreter Lock (GIL) that ensures only one thread can be run at a time. But if you're doing a lot of blocking IO (such as HTTP calls to external APIs like Twitter), Puma still improves MRI's throughput by allowing blocking IO to be run concurrently (EventMachine-based servers such as Thin turn off this ability, requiring you to use special libraries). Your mileage may vary. In order to get the best throughput, it is highly recommended that you use a Ruby implementation with real threads like [Rubinius](http://rubini.us) or [JRuby](http://jruby.org)."
|
11
11
|
s.email = ["evan@phx.io"]
|
12
12
|
s.executables = ["puma", "pumactl"]
|
13
13
|
s.extensions = ["ext/puma_http11/extconf.rb"]
|
14
14
|
s.extra_rdoc_files = ["History.txt", "Manifest.txt"]
|
15
|
-
s.files = ["COPYING", "Gemfile", "Gemfile.lock", "History.txt", "LICENSE", "Manifest.txt", "README.md", "Rakefile", "TODO", "bin/puma", "bin/pumactl", "examples/CA/cacert.pem", "examples/CA/newcerts/cert_1.pem", "examples/CA/newcerts/cert_2.pem", "examples/CA/private/cakeypair.pem", "examples/CA/serial", "examples/config.rb", "examples/puma/cert_puma.pem", "examples/puma/csr_puma.pem", "examples/puma/puma_keypair.pem", "examples/qc_config.rb", "ext/puma_http11/PumaHttp11Service.java", "ext/puma_http11/ext_help.h", "ext/puma_http11/extconf.rb", "ext/puma_http11/http11_parser.c", "ext/puma_http11/http11_parser.h", "ext/puma_http11/http11_parser.java.rl", "ext/puma_http11/http11_parser.rl", "ext/puma_http11/http11_parser_common.rl", "ext/puma_http11/org/jruby/puma/Http11.java", "ext/puma_http11/org/jruby/puma/Http11Parser.java", "ext/puma_http11/puma_http11.c", "lib/puma.rb", "lib/puma/app/status.rb", "lib/puma/cli.rb", "lib/puma/client.rb", "lib/puma/compat.rb", "lib/puma/configuration.rb", "lib/puma/const.rb", "lib/puma/control_cli.rb", "lib/puma/detect.rb", "lib/puma/events.rb", "lib/puma/jruby_restart.rb", "lib/puma/null_io.rb", "lib/puma/rack_patch.rb", "lib/puma/reactor.rb", "lib/puma/server.rb", "lib/puma/thread_pool.rb", "lib/rack/handler/puma.rb", "puma.gemspec", "test/ab_rs.rb", "test/config/app.rb", "test/hello-post.ru", "test/hello.ru", "test/lobster.ru", "test/mime.yaml", "test/slow.ru", "test/test_app_status.rb", "test/test_cli.rb", "test/test_config.rb", "test/test_http10.rb", "test/test_http11.rb", "test/test_integration.rb", "test/test_null_io.rb", "test/test_persistent.rb", "test/test_puma_server.rb", "test/test_rack_handler.rb", "test/test_rack_server.rb", "test/test_thread_pool.rb", "test/test_unix_socket.rb", "test/test_ws.rb", "test/testhelp.rb", "tools/trickletest.rb"]
|
15
|
+
s.files = ["COPYING", "Gemfile", "Gemfile.lock", "History.txt", "LICENSE", "Manifest.txt", "README.md", "Rakefile", "TODO", "bin/puma", "bin/pumactl", "examples/CA/cacert.pem", "examples/CA/newcerts/cert_1.pem", "examples/CA/newcerts/cert_2.pem", "examples/CA/private/cakeypair.pem", "examples/CA/serial", "examples/config.rb", "examples/puma/cert_puma.pem", "examples/puma/csr_puma.pem", "examples/puma/puma_keypair.pem", "examples/qc_config.rb", "ext/puma_http11/PumaHttp11Service.java", "ext/puma_http11/ext_help.h", "ext/puma_http11/extconf.rb", "ext/puma_http11/http11_parser.c", "ext/puma_http11/http11_parser.h", "ext/puma_http11/http11_parser.java.rl", "ext/puma_http11/http11_parser.rl", "ext/puma_http11/http11_parser_common.rl", "ext/puma_http11/org/jruby/puma/Http11.java", "ext/puma_http11/org/jruby/puma/Http11Parser.java", "ext/puma_http11/puma_http11.c", "lib/puma.rb", "lib/puma/app/status.rb", "lib/puma/cli.rb", "lib/puma/client.rb", "lib/puma/compat.rb", "lib/puma/configuration.rb", "lib/puma/const.rb", "lib/puma/control_cli.rb", "lib/puma/detect.rb", "lib/puma/events.rb", "lib/puma/jruby_restart.rb", "lib/puma/null_io.rb", "lib/puma/rack_patch.rb", "lib/puma/reactor.rb", "lib/puma/server.rb", "lib/puma/thread_pool.rb", "lib/rack/handler/puma.rb", "puma.gemspec", "test/ab_rs.rb", "test/config/app.rb", "test/hello-post.ru", "test/hello.ru", "test/lobster.ru", "test/mime.yaml", "test/slow.ru", "test/test_app_status.rb", "test/test_cli.rb", "test/test_config.rb", "test/test_http10.rb", "test/test_http11.rb", "test/test_integration.rb", "test/test_null_io.rb", "test/test_persistent.rb", "test/test_puma_server.rb", "test/test_rack_handler.rb", "test/test_rack_server.rb", "test/test_thread_pool.rb", "test/test_unix_socket.rb", "test/test_ws.rb", "test/testhelp.rb", "tools/trickletest.rb", "test/test_iobuffer.rb"]
|
16
16
|
s.homepage = "http://puma.io"
|
17
17
|
s.rdoc_options = ["--main", "README.md"]
|
18
18
|
s.require_paths = ["lib"]
|
@@ -20,7 +20,7 @@ Gem::Specification.new do |s|
|
|
20
20
|
s.rubyforge_project = "puma"
|
21
21
|
s.rubygems_version = "1.8.24"
|
22
22
|
s.summary = "Puma is a simple, fast, and highly concurrent HTTP 1.1 server for Ruby web applications"
|
23
|
-
s.test_files = ["test/test_app_status.rb", "test/test_cli.rb", "test/test_config.rb", "test/test_http10.rb", "test/test_http11.rb", "test/test_integration.rb", "test/test_null_io.rb", "test/test_persistent.rb", "test/test_puma_server.rb", "test/test_rack_handler.rb", "test/test_rack_server.rb", "test/test_thread_pool.rb", "test/test_unix_socket.rb", "test/test_ws.rb"]
|
23
|
+
s.test_files = ["test/test_app_status.rb", "test/test_cli.rb", "test/test_config.rb", "test/test_http10.rb", "test/test_http11.rb", "test/test_integration.rb", "test/test_iobuffer.rb", "test/test_null_io.rb", "test/test_persistent.rb", "test/test_puma_server.rb", "test/test_rack_handler.rb", "test/test_rack_server.rb", "test/test_thread_pool.rb", "test/test_unix_socket.rb", "test/test_ws.rb"]
|
24
24
|
|
25
25
|
if s.respond_to? :specification_version then
|
26
26
|
s.specification_version = 3
|
data/test/test_integration.rb
CHANGED
@@ -3,6 +3,7 @@ require 'test/unit'
|
|
3
3
|
require 'socket'
|
4
4
|
require 'timeout'
|
5
5
|
require 'net/http'
|
6
|
+
require 'tempfile'
|
6
7
|
|
7
8
|
require 'puma/cli'
|
8
9
|
require 'puma/control_cli'
|
@@ -15,6 +16,7 @@ class TestIntegration < Test::Unit::TestCase
|
|
15
16
|
@tcp_port = 9998
|
16
17
|
|
17
18
|
@server = nil
|
19
|
+
@script = nil
|
18
20
|
end
|
19
21
|
|
20
22
|
def teardown
|
@@ -27,14 +29,27 @@ class TestIntegration < Test::Unit::TestCase
|
|
27
29
|
Process.wait @server.pid
|
28
30
|
@server.close
|
29
31
|
end
|
32
|
+
|
33
|
+
if @script
|
34
|
+
@script.close!
|
35
|
+
end
|
30
36
|
end
|
31
37
|
|
32
38
|
def server(opts)
|
33
39
|
core = "#{Gem.ruby} -rubygems -Ilib bin/puma"
|
34
40
|
cmd = "#{core} --restart-cmd '#{core}' -b tcp://127.0.0.1:#{@tcp_port} #{opts}"
|
35
|
-
|
41
|
+
tf = Tempfile.new "puma-test"
|
42
|
+
tf.puts "exec #{cmd}"
|
43
|
+
tf.close
|
44
|
+
|
45
|
+
@script = tf
|
46
|
+
|
47
|
+
@server = IO.popen("sh #{tf.path}", "r")
|
48
|
+
|
49
|
+
true while @server.gets =~ /Ctrl-C/
|
36
50
|
|
37
51
|
sleep 1
|
52
|
+
|
38
53
|
@server
|
39
54
|
end
|
40
55
|
|
@@ -80,7 +95,34 @@ class TestIntegration < Test::Unit::TestCase
|
|
80
95
|
s.readpartial(20)
|
81
96
|
signal :USR2
|
82
97
|
|
83
|
-
|
98
|
+
true while @server.gets =~ /Ctrl-C/
|
99
|
+
sleep 1
|
100
|
+
|
101
|
+
s.write "GET / HTTP/1.1\r\n\r\n"
|
102
|
+
|
103
|
+
assert_raises Errno::ECONNRESET do
|
104
|
+
Timeout.timeout(2) do
|
105
|
+
s.read(2)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
s = TCPSocket.new "localhost", @tcp_port
|
110
|
+
s << "GET / HTTP/1.0\r\n\r\n"
|
111
|
+
assert_equal "Hello World", s.read.split("\r\n").last
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_restart_closes_keepalive_sockets_workers
|
115
|
+
server("-q -w 2 test/hello.ru")
|
116
|
+
|
117
|
+
s = TCPSocket.new "localhost", @tcp_port
|
118
|
+
s << "GET / HTTP/1.1\r\n\r\n"
|
119
|
+
true until s.gets == "\r\n"
|
120
|
+
|
121
|
+
s.readpartial(20)
|
122
|
+
signal :USR2
|
123
|
+
|
124
|
+
true while @server.gets =~ /Ctrl-C/
|
125
|
+
sleep 1
|
84
126
|
|
85
127
|
s.write "GET / HTTP/1.1\r\n\r\n"
|
86
128
|
|
@@ -94,4 +136,13 @@ class TestIntegration < Test::Unit::TestCase
|
|
94
136
|
s << "GET / HTTP/1.0\r\n\r\n"
|
95
137
|
assert_equal "Hello World", s.read.split("\r\n").last
|
96
138
|
end
|
139
|
+
|
140
|
+
def test_bad_query_string_outputs_400
|
141
|
+
server "-q test/hello.ru 2>&1"
|
142
|
+
|
143
|
+
s = TCPSocket.new "localhost", @tcp_port
|
144
|
+
s << "GET /?h=% HTTP/1.0\r\n\r\n"
|
145
|
+
data = s.read
|
146
|
+
assert_equal "HTTP/1.1 400 Bad Request\r\n\r\n", data
|
147
|
+
end
|
97
148
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'puma/io_buffer'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
class TestIOBuffer < Test::Unit::TestCase
|
5
|
+
attr_accessor :iobuf
|
6
|
+
def setup
|
7
|
+
self.iobuf = Puma::IOBuffer.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_initial_size
|
11
|
+
assert_equal 0, iobuf.used
|
12
|
+
assert iobuf.capacity > 0
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_append_op
|
16
|
+
iobuf << "abc"
|
17
|
+
assert_equal "abc", iobuf.to_s
|
18
|
+
iobuf << "123"
|
19
|
+
assert_equal "abc123", iobuf.to_s
|
20
|
+
assert_equal 6, iobuf.used
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_append
|
24
|
+
expected = "mary had a little lamb"
|
25
|
+
iobuf.append("mary", " ", "had ", "a little", " lamb")
|
26
|
+
assert_equal expected, iobuf.to_s
|
27
|
+
assert_equal expected.length, iobuf.used
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_reset
|
31
|
+
iobuf << "content"
|
32
|
+
assert_equal "content", iobuf.to_s
|
33
|
+
iobuf.reset
|
34
|
+
assert_equal 0, iobuf.used
|
35
|
+
assert_equal "", iobuf.to_s
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
data/test/test_puma_server.rb
CHANGED
@@ -3,6 +3,7 @@ require 'test/unit'
|
|
3
3
|
require 'socket'
|
4
4
|
require 'openssl'
|
5
5
|
|
6
|
+
require 'puma/minissl'
|
6
7
|
require 'puma/server'
|
7
8
|
|
8
9
|
require 'net/https'
|
@@ -18,8 +19,13 @@ class TestPumaServer < Test::Unit::TestCase
|
|
18
19
|
@events = Puma::Events.new STDOUT, STDERR
|
19
20
|
@server = Puma::Server.new @app, @events
|
20
21
|
|
21
|
-
|
22
|
-
|
22
|
+
if defined?(JRUBY_VERSION)
|
23
|
+
@ssl_key = File.expand_path "../../examples/puma/keystore.jks", __FILE__
|
24
|
+
@ssl_cert = @ssl_key
|
25
|
+
else
|
26
|
+
@ssl_key = File.expand_path "../../examples/puma/puma_keypair.pem", __FILE__
|
27
|
+
@ssl_cert = File.expand_path "../../examples/puma/cert_puma.pem", __FILE__
|
28
|
+
end
|
23
29
|
end
|
24
30
|
|
25
31
|
def teardown
|
@@ -27,13 +33,12 @@ class TestPumaServer < Test::Unit::TestCase
|
|
27
33
|
end
|
28
34
|
|
29
35
|
def test_url_scheme_for_https
|
30
|
-
ctx =
|
31
|
-
|
32
|
-
ctx.key = OpenSSL::PKey::RSA.new File.read(@ssl_key)
|
36
|
+
ctx = Puma::MiniSSL::Context.new
|
33
37
|
|
34
|
-
ctx.
|
38
|
+
ctx.key = @ssl_key
|
39
|
+
ctx.cert = @ssl_cert
|
35
40
|
|
36
|
-
ctx.verify_mode =
|
41
|
+
ctx.verify_mode = Puma::MiniSSL::VERIFY_NONE
|
37
42
|
|
38
43
|
@server.add_ssl_listener @host, @port, ctx
|
39
44
|
@server.run
|
@@ -0,0 +1,54 @@
|
|
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/config/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/*config/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/puma
ADDED
@@ -0,0 +1,332 @@
|
|
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
|
+
|
27
|
+
# Load the VERBOSE setting and other rcS variables
|
28
|
+
. /lib/init/vars.sh
|
29
|
+
|
30
|
+
# Define LSB log_* functions.
|
31
|
+
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
|
32
|
+
. /lib/lsb/init-functions
|
33
|
+
|
34
|
+
#
|
35
|
+
# Function that starts the jungle
|
36
|
+
#
|
37
|
+
do_start() {
|
38
|
+
log_daemon_msg "=> Running the jungle..."
|
39
|
+
for i in $JUNGLE; do
|
40
|
+
dir=`echo $i | cut -d , -f 1`
|
41
|
+
user=`echo $i | cut -d , -f 2`
|
42
|
+
config_file=`echo $i | cut -d , -f 3`
|
43
|
+
if [ "$config_file" = "" ]; then
|
44
|
+
config_file="$dir/config/puma.rb"
|
45
|
+
fi
|
46
|
+
log_file=`echo $i | cut -d , -f 4`
|
47
|
+
if [ "$log_file" = "" ]; then
|
48
|
+
log_file="$dir/log/puma.log"
|
49
|
+
fi
|
50
|
+
do_start_one $dir $user $config_file $log_file
|
51
|
+
done
|
52
|
+
}
|
53
|
+
|
54
|
+
do_start_one() {
|
55
|
+
PIDFILE=$1/tmp/puma/pid
|
56
|
+
if [ -e $PIDFILE ]; then
|
57
|
+
PID=`cat $PIDFILE`
|
58
|
+
# If the puma isn't running, run it, otherwise restart it.
|
59
|
+
if [ "`ps -A -o pid= | grep -c $PID`" -eq 0 ]; then
|
60
|
+
do_start_one_do $1 $2 $3 $4
|
61
|
+
else
|
62
|
+
do_restart_one $1
|
63
|
+
fi
|
64
|
+
else
|
65
|
+
do_start_one_do $1 $2 $3 $4
|
66
|
+
fi
|
67
|
+
}
|
68
|
+
|
69
|
+
do_start_one_do() {
|
70
|
+
log_daemon_msg "--> Woke up puma $1"
|
71
|
+
log_daemon_msg "user $2"
|
72
|
+
log_daemon_msg "log to $4"
|
73
|
+
start-stop-daemon --verbose --start --chdir $1 --chuid $2 --background --exec $RUNPUMA -- $1 $3 $4
|
74
|
+
}
|
75
|
+
|
76
|
+
#
|
77
|
+
# Function that stops the jungle
|
78
|
+
#
|
79
|
+
do_stop() {
|
80
|
+
log_daemon_msg "=> Putting all the beasts to bed..."
|
81
|
+
for i in $JUNGLE; do
|
82
|
+
dir=`echo $i | cut -d , -f 1`
|
83
|
+
do_stop_one $dir
|
84
|
+
done
|
85
|
+
}
|
86
|
+
#
|
87
|
+
# Function that stops the daemon/service
|
88
|
+
#
|
89
|
+
do_stop_one() {
|
90
|
+
log_daemon_msg "--> Stopping $1"
|
91
|
+
PIDFILE=$1/tmp/puma/pid
|
92
|
+
STATEFILE=$1/tmp/puma/state
|
93
|
+
if [ -e $PIDFILE ]; then
|
94
|
+
PID=`cat $PIDFILE`
|
95
|
+
if [ "`ps -A -o pid= | grep -c $PID`" -eq 0 ]; then
|
96
|
+
log_daemon_msg "---> Puma $1 isn't running."
|
97
|
+
else
|
98
|
+
log_daemon_msg "---> About to kill PID `cat $PIDFILE`"
|
99
|
+
pumactl --state $STATEFILE stop
|
100
|
+
# Many daemons don't delete their pidfiles when they exit.
|
101
|
+
rm -f $PIDFILE $STATEFILE
|
102
|
+
fi
|
103
|
+
else
|
104
|
+
log_daemon_msg "---> No puma here..."
|
105
|
+
fi
|
106
|
+
return 0
|
107
|
+
}
|
108
|
+
|
109
|
+
#
|
110
|
+
# Function that restarts the jungle
|
111
|
+
#
|
112
|
+
do_restart() {
|
113
|
+
for i in $JUNGLE; do
|
114
|
+
dir=`echo $i | cut -d , -f 1`
|
115
|
+
do_restart_one $dir
|
116
|
+
done
|
117
|
+
}
|
118
|
+
|
119
|
+
#
|
120
|
+
# Function that sends a SIGUSR2 to the daemon/service
|
121
|
+
#
|
122
|
+
do_restart_one() {
|
123
|
+
PIDFILE=$1/tmp/puma/pid
|
124
|
+
i=`grep $1 $CONFIG`
|
125
|
+
dir=`echo $i | cut -d , -f 1`
|
126
|
+
|
127
|
+
if [ -e $PIDFILE ]; then
|
128
|
+
log_daemon_msg "--> About to restart puma $1"
|
129
|
+
pumactl --state $dir/tmp/puma/state restart
|
130
|
+
# kill -s USR2 `cat $PIDFILE`
|
131
|
+
# TODO Check if process exist
|
132
|
+
else
|
133
|
+
log_daemon_msg "--> Your puma was never playing... Let's get it out there first"
|
134
|
+
user=`echo $i | cut -d , -f 2`
|
135
|
+
config_file=`echo $i | cut -d , -f 3`
|
136
|
+
if [ "$config_file" = "" ]; then
|
137
|
+
config_file="$dir/config/puma.rb"
|
138
|
+
fi
|
139
|
+
log_file=`echo $i | cut -d , -f 4`
|
140
|
+
if [ "$log_file" = "" ]; then
|
141
|
+
log_file="$dir/log/puma.log"
|
142
|
+
fi
|
143
|
+
do_start_one $dir $user $config_file $log_file
|
144
|
+
fi
|
145
|
+
return 0
|
146
|
+
}
|
147
|
+
|
148
|
+
#
|
149
|
+
# Function that statuss the jungle
|
150
|
+
#
|
151
|
+
do_status() {
|
152
|
+
for i in $JUNGLE; do
|
153
|
+
dir=`echo $i | cut -d , -f 1`
|
154
|
+
do_status_one $dir
|
155
|
+
done
|
156
|
+
}
|
157
|
+
|
158
|
+
#
|
159
|
+
# Function that sends a SIGUSR2 to the daemon/service
|
160
|
+
#
|
161
|
+
do_status_one() {
|
162
|
+
PIDFILE=$1/tmp/puma/pid
|
163
|
+
i=`grep $1 $CONFIG`
|
164
|
+
dir=`echo $i | cut -d , -f 1`
|
165
|
+
|
166
|
+
if [ -e $PIDFILE ]; then
|
167
|
+
log_daemon_msg "--> About to status puma $1"
|
168
|
+
pumactl --state $dir/tmp/puma/state stats
|
169
|
+
# kill -s USR2 `cat $PIDFILE`
|
170
|
+
# TODO Check if process exist
|
171
|
+
else
|
172
|
+
log_daemon_msg "--> $1 isn't there :(..."
|
173
|
+
fi
|
174
|
+
return 0
|
175
|
+
}
|
176
|
+
|
177
|
+
do_add() {
|
178
|
+
str=""
|
179
|
+
# App's directory
|
180
|
+
if [ -d "$1" ]; then
|
181
|
+
if [ "`grep -c "^$1" $CONFIG`" -eq 0 ]; then
|
182
|
+
str=$1
|
183
|
+
else
|
184
|
+
echo "The app is already being managed. Remove it if you want to update its config."
|
185
|
+
exit 1
|
186
|
+
fi
|
187
|
+
else
|
188
|
+
echo "The directory $1 doesn't exist."
|
189
|
+
exit 1
|
190
|
+
fi
|
191
|
+
# User to run it as
|
192
|
+
if [ "`grep -c "^$2:" /etc/passwd`" -eq 0 ]; then
|
193
|
+
echo "The user $2 doesn't exist."
|
194
|
+
exit 1
|
195
|
+
else
|
196
|
+
str="$str,$2"
|
197
|
+
fi
|
198
|
+
# Config file
|
199
|
+
if [ "$3" != "" ]; then
|
200
|
+
if [ -e $3 ]; then
|
201
|
+
str="$str,$3"
|
202
|
+
else
|
203
|
+
echo "The config file $3 doesn't exist."
|
204
|
+
exit 1
|
205
|
+
fi
|
206
|
+
fi
|
207
|
+
# Log file
|
208
|
+
if [ "$4" != "" ]; then
|
209
|
+
str="$str,$4"
|
210
|
+
fi
|
211
|
+
|
212
|
+
# Add it to the jungle
|
213
|
+
echo $str >> $CONFIG
|
214
|
+
log_daemon_msg "Added a Puma to the jungle: $str. You still have to start it though."
|
215
|
+
}
|
216
|
+
|
217
|
+
do_remove() {
|
218
|
+
if [ "`grep -c "^$1" $CONFIG`" -eq 0 ]; then
|
219
|
+
echo "There's no app $1 to remove."
|
220
|
+
else
|
221
|
+
# Stop it first.
|
222
|
+
do_stop_one $1
|
223
|
+
# Remove it from the config.
|
224
|
+
sed -i "\\:^$1:d" $CONFIG
|
225
|
+
log_daemon_msg "Removed a Puma from the jungle: $1."
|
226
|
+
fi
|
227
|
+
}
|
228
|
+
|
229
|
+
case "$1" in
|
230
|
+
start)
|
231
|
+
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
|
232
|
+
if [ "$#" -eq 1 ]; then
|
233
|
+
do_start
|
234
|
+
else
|
235
|
+
i=`grep $2 $CONFIG`
|
236
|
+
dir=`echo $i | cut -d , -f 1`
|
237
|
+
user=`echo $i | cut -d , -f 2`
|
238
|
+
config_file=`echo $i | cut -d , -f 3`
|
239
|
+
if [ "$config_file" = "" ]; then
|
240
|
+
config_file="$dir/config/puma.rb"
|
241
|
+
fi
|
242
|
+
log_file=`echo $i | cut -d , -f 4`
|
243
|
+
if [ "$log_file" = "" ]; then
|
244
|
+
log_file="$dir/log/puma.log"
|
245
|
+
fi
|
246
|
+
do_start_one $dir $user $config_file $log_file
|
247
|
+
fi
|
248
|
+
case "$?" in
|
249
|
+
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
250
|
+
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
251
|
+
esac
|
252
|
+
;;
|
253
|
+
stop)
|
254
|
+
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
|
255
|
+
if [ "$#" -eq 1 ]; then
|
256
|
+
do_stop
|
257
|
+
else
|
258
|
+
i=`grep $2 $CONFIG`
|
259
|
+
dir=`echo $i | cut -d , -f 1`
|
260
|
+
do_stop_one $dir
|
261
|
+
fi
|
262
|
+
case "$?" in
|
263
|
+
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
264
|
+
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
265
|
+
esac
|
266
|
+
;;
|
267
|
+
status)
|
268
|
+
# TODO Implement.
|
269
|
+
log_daemon_msg "Status $DESC" "$NAME"
|
270
|
+
if [ "$#" -eq 1 ]; then
|
271
|
+
do_status
|
272
|
+
else
|
273
|
+
i=`grep $2 $CONFIG`
|
274
|
+
dir=`echo $i | cut -d , -f 1`
|
275
|
+
do_status_one $dir
|
276
|
+
fi
|
277
|
+
case "$?" in
|
278
|
+
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
279
|
+
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
280
|
+
esac
|
281
|
+
;;
|
282
|
+
restart)
|
283
|
+
log_daemon_msg "Restarting $DESC" "$NAME"
|
284
|
+
if [ "$#" -eq 1 ]; then
|
285
|
+
do_restart
|
286
|
+
else
|
287
|
+
i=`grep $2 $CONFIG`
|
288
|
+
dir=`echo $i | cut -d , -f 1`
|
289
|
+
do_restart_one $dir
|
290
|
+
fi
|
291
|
+
case "$?" in
|
292
|
+
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
293
|
+
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
294
|
+
esac
|
295
|
+
;;
|
296
|
+
add)
|
297
|
+
if [ "$#" -lt 3 ]; then
|
298
|
+
echo "Please, specifiy the app's directory and the user that will run it at least."
|
299
|
+
echo " Usage: $SCRIPTNAME add /path/to/app user /path/to/app/config/puma.rb /path/to/app/config/log/puma.log"
|
300
|
+
echo " config and log are optionals."
|
301
|
+
exit 1
|
302
|
+
else
|
303
|
+
do_add $2 $3 $4 $5
|
304
|
+
fi
|
305
|
+
case "$?" in
|
306
|
+
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
307
|
+
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
308
|
+
esac
|
309
|
+
;;
|
310
|
+
remove)
|
311
|
+
if [ "$#" -lt 2 ]; then
|
312
|
+
echo "Please, specifiy the app's directory to remove."
|
313
|
+
exit 1
|
314
|
+
else
|
315
|
+
do_remove $2
|
316
|
+
fi
|
317
|
+
case "$?" in
|
318
|
+
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
|
319
|
+
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
|
320
|
+
esac
|
321
|
+
;;
|
322
|
+
*)
|
323
|
+
echo "Usage:" >&2
|
324
|
+
echo " Run the jungle: $SCRIPTNAME {start|stop|status|restart}" >&2
|
325
|
+
echo " Add a Puma: $SCRIPTNAME add /path/to/app user /path/to/app/config/puma.rb /path/to/app/config/log/puma.log"
|
326
|
+
echo " config and log are optionals."
|
327
|
+
echo " Remove a Puma: $SCRIPTNAME remove /path/to/app"
|
328
|
+
echo " On a Puma: $SCRIPTNAME {start|stop|status|restart} PUMA-NAME" >&2
|
329
|
+
exit 3
|
330
|
+
;;
|
331
|
+
esac
|
332
|
+
:
|