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.

@@ -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 work
97
+ block.call(work, *extra)
95
98
  end
96
99
 
97
100
  mutex.synchronize do
@@ -2,17 +2,17 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "puma"
5
- s.version = "1.6.3"
5
+ s.version = "2.0.0.b1"
6
6
 
7
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
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-04"
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
@@ -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
- @server = IO.popen(cmd, "r")
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
- sleep 3
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
@@ -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
- @ssl_key = File.expand_path "../../examples/puma/puma_keypair.pem", __FILE__
22
- @ssl_cert = File.expand_path "../../examples/puma/cert_puma.pem", __FILE__
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 = OpenSSL::SSL::SSLContext.new
31
-
32
- ctx.key = OpenSSL::PKey::RSA.new File.read(@ssl_key)
36
+ ctx = Puma::MiniSSL::Context.new
33
37
 
34
- ctx.cert = OpenSSL::X509::Certificate.new File.read(@ssl_cert)
38
+ ctx.key = @ssl_key
39
+ ctx.cert = @ssl_cert
35
40
 
36
- ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE
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
+ ```
@@ -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
+ :