giraffesoft-unicorn 0.93.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.CHANGELOG.old +25 -0
- data/.document +16 -0
- data/.gitignore +20 -0
- data/.mailmap +26 -0
- data/CONTRIBUTORS +31 -0
- data/COPYING +339 -0
- data/DESIGN +105 -0
- data/Documentation/.gitignore +5 -0
- data/Documentation/GNUmakefile +30 -0
- data/Documentation/unicorn.1.txt +167 -0
- data/Documentation/unicorn_rails.1.txt +169 -0
- data/GIT-VERSION-GEN +40 -0
- data/GNUmakefile +270 -0
- data/HACKING +113 -0
- data/KNOWN_ISSUES +40 -0
- data/LICENSE +55 -0
- data/PHILOSOPHY +144 -0
- data/README +153 -0
- data/Rakefile +108 -0
- data/SIGNALS +97 -0
- data/TODO +16 -0
- data/TUNING +70 -0
- data/bin/unicorn +165 -0
- data/bin/unicorn_rails +208 -0
- data/examples/echo.ru +27 -0
- data/examples/git.ru +13 -0
- data/examples/init.sh +53 -0
- data/ext/unicorn_http/c_util.h +107 -0
- data/ext/unicorn_http/common_field_optimization.h +111 -0
- data/ext/unicorn_http/ext_help.h +73 -0
- data/ext/unicorn_http/extconf.rb +14 -0
- data/ext/unicorn_http/global_variables.h +91 -0
- data/ext/unicorn_http/unicorn_http.rl +715 -0
- data/ext/unicorn_http/unicorn_http_common.rl +74 -0
- data/lib/unicorn.rb +730 -0
- data/lib/unicorn/app/exec_cgi.rb +150 -0
- data/lib/unicorn/app/inetd.rb +109 -0
- data/lib/unicorn/app/old_rails.rb +31 -0
- data/lib/unicorn/app/old_rails/static.rb +60 -0
- data/lib/unicorn/cgi_wrapper.rb +145 -0
- data/lib/unicorn/configurator.rb +403 -0
- data/lib/unicorn/const.rb +37 -0
- data/lib/unicorn/http_request.rb +74 -0
- data/lib/unicorn/http_response.rb +74 -0
- data/lib/unicorn/launcher.rb +39 -0
- data/lib/unicorn/socket_helper.rb +138 -0
- data/lib/unicorn/tee_input.rb +174 -0
- data/lib/unicorn/util.rb +64 -0
- data/local.mk.sample +53 -0
- data/setup.rb +1586 -0
- data/test/aggregate.rb +15 -0
- data/test/benchmark/README +50 -0
- data/test/benchmark/dd.ru +18 -0
- data/test/exec/README +5 -0
- data/test/exec/test_exec.rb +855 -0
- data/test/rails/app-1.2.3/.gitignore +2 -0
- data/test/rails/app-1.2.3/Rakefile +7 -0
- data/test/rails/app-1.2.3/app/controllers/application.rb +6 -0
- data/test/rails/app-1.2.3/app/controllers/foo_controller.rb +36 -0
- data/test/rails/app-1.2.3/app/helpers/application_helper.rb +4 -0
- data/test/rails/app-1.2.3/config/boot.rb +11 -0
- data/test/rails/app-1.2.3/config/database.yml +12 -0
- data/test/rails/app-1.2.3/config/environment.rb +13 -0
- data/test/rails/app-1.2.3/config/environments/development.rb +9 -0
- data/test/rails/app-1.2.3/config/environments/production.rb +5 -0
- data/test/rails/app-1.2.3/config/routes.rb +6 -0
- data/test/rails/app-1.2.3/db/.gitignore +0 -0
- data/test/rails/app-1.2.3/public/404.html +1 -0
- data/test/rails/app-1.2.3/public/500.html +1 -0
- data/test/rails/app-2.0.2/.gitignore +2 -0
- data/test/rails/app-2.0.2/Rakefile +7 -0
- data/test/rails/app-2.0.2/app/controllers/application.rb +4 -0
- data/test/rails/app-2.0.2/app/controllers/foo_controller.rb +36 -0
- data/test/rails/app-2.0.2/app/helpers/application_helper.rb +4 -0
- data/test/rails/app-2.0.2/config/boot.rb +11 -0
- data/test/rails/app-2.0.2/config/database.yml +12 -0
- data/test/rails/app-2.0.2/config/environment.rb +17 -0
- data/test/rails/app-2.0.2/config/environments/development.rb +8 -0
- data/test/rails/app-2.0.2/config/environments/production.rb +5 -0
- data/test/rails/app-2.0.2/config/routes.rb +6 -0
- data/test/rails/app-2.0.2/db/.gitignore +0 -0
- data/test/rails/app-2.0.2/public/404.html +1 -0
- data/test/rails/app-2.0.2/public/500.html +1 -0
- data/test/rails/app-2.1.2/.gitignore +2 -0
- data/test/rails/app-2.1.2/Rakefile +7 -0
- data/test/rails/app-2.1.2/app/controllers/application.rb +4 -0
- data/test/rails/app-2.1.2/app/controllers/foo_controller.rb +36 -0
- data/test/rails/app-2.1.2/app/helpers/application_helper.rb +4 -0
- data/test/rails/app-2.1.2/config/boot.rb +111 -0
- data/test/rails/app-2.1.2/config/database.yml +12 -0
- data/test/rails/app-2.1.2/config/environment.rb +17 -0
- data/test/rails/app-2.1.2/config/environments/development.rb +7 -0
- data/test/rails/app-2.1.2/config/environments/production.rb +5 -0
- data/test/rails/app-2.1.2/config/routes.rb +6 -0
- data/test/rails/app-2.1.2/db/.gitignore +0 -0
- data/test/rails/app-2.1.2/public/404.html +1 -0
- data/test/rails/app-2.1.2/public/500.html +1 -0
- data/test/rails/app-2.2.2/.gitignore +2 -0
- data/test/rails/app-2.2.2/Rakefile +7 -0
- data/test/rails/app-2.2.2/app/controllers/application.rb +4 -0
- data/test/rails/app-2.2.2/app/controllers/foo_controller.rb +36 -0
- data/test/rails/app-2.2.2/app/helpers/application_helper.rb +4 -0
- data/test/rails/app-2.2.2/config/boot.rb +111 -0
- data/test/rails/app-2.2.2/config/database.yml +12 -0
- data/test/rails/app-2.2.2/config/environment.rb +17 -0
- data/test/rails/app-2.2.2/config/environments/development.rb +7 -0
- data/test/rails/app-2.2.2/config/environments/production.rb +5 -0
- data/test/rails/app-2.2.2/config/routes.rb +6 -0
- data/test/rails/app-2.2.2/db/.gitignore +0 -0
- data/test/rails/app-2.2.2/public/404.html +1 -0
- data/test/rails/app-2.2.2/public/500.html +1 -0
- data/test/rails/app-2.3.3.1/.gitignore +2 -0
- data/test/rails/app-2.3.3.1/Rakefile +7 -0
- data/test/rails/app-2.3.3.1/app/controllers/application_controller.rb +5 -0
- data/test/rails/app-2.3.3.1/app/controllers/foo_controller.rb +36 -0
- data/test/rails/app-2.3.3.1/app/helpers/application_helper.rb +4 -0
- data/test/rails/app-2.3.3.1/config/boot.rb +109 -0
- data/test/rails/app-2.3.3.1/config/database.yml +12 -0
- data/test/rails/app-2.3.3.1/config/environment.rb +17 -0
- data/test/rails/app-2.3.3.1/config/environments/development.rb +7 -0
- data/test/rails/app-2.3.3.1/config/environments/production.rb +6 -0
- data/test/rails/app-2.3.3.1/config/routes.rb +6 -0
- data/test/rails/app-2.3.3.1/db/.gitignore +0 -0
- data/test/rails/app-2.3.3.1/public/404.html +1 -0
- data/test/rails/app-2.3.3.1/public/500.html +1 -0
- data/test/rails/app-2.3.3.1/public/x.txt +1 -0
- data/test/rails/test_rails.rb +280 -0
- data/test/test_helper.rb +296 -0
- data/test/unit/test_configurator.rb +150 -0
- data/test/unit/test_http_parser.rb +492 -0
- data/test/unit/test_http_parser_ng.rb +308 -0
- data/test/unit/test_request.rb +184 -0
- data/test/unit/test_response.rb +110 -0
- data/test/unit/test_server.rb +188 -0
- data/test/unit/test_signals.rb +202 -0
- data/test/unit/test_socket_helper.rb +133 -0
- data/test/unit/test_tee_input.rb +229 -0
- data/test/unit/test_upload.rb +297 -0
- data/test/unit/test_util.rb +96 -0
- data/unicorn.gemspec +42 -0
- metadata +228 -0
data/SIGNALS
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
== Signal handling
|
|
2
|
+
|
|
3
|
+
In general, signals need only be sent to the master process. However,
|
|
4
|
+
the signals Unicorn uses internally to communicate with the worker
|
|
5
|
+
processes are documented here as well. With the exception of TTIN/TTOU,
|
|
6
|
+
signal handling matches the behavior of {nginx}[http://nginx.net/] so it
|
|
7
|
+
should be possible to easily share process management scripts between
|
|
8
|
+
Unicorn and nginx.
|
|
9
|
+
|
|
10
|
+
=== Master Process
|
|
11
|
+
|
|
12
|
+
* HUP - reload config file, app, and gracefully restart all workers
|
|
13
|
+
|
|
14
|
+
* INT/TERM - quick shutdown, kills all workers immediately
|
|
15
|
+
|
|
16
|
+
* QUIT - graceful shutdown, waits for workers to finish their
|
|
17
|
+
current request before finishing.
|
|
18
|
+
|
|
19
|
+
* USR1 - reopen all logs owned by the master and all workers
|
|
20
|
+
See Unicorn::Util.reopen_logs for what is considered a log.
|
|
21
|
+
|
|
22
|
+
* USR2 - reexecute the running binary. A separate QUIT
|
|
23
|
+
should be sent to the original process once the child is verified to
|
|
24
|
+
be up and running.
|
|
25
|
+
|
|
26
|
+
* WINCH - gracefully stops workers but keep the master running.
|
|
27
|
+
This will only work for daemonized processes.
|
|
28
|
+
|
|
29
|
+
* TTIN - increment the number of worker processes by one
|
|
30
|
+
|
|
31
|
+
* TTOU - decrement the number of worker processes by one
|
|
32
|
+
|
|
33
|
+
=== Worker Processes
|
|
34
|
+
|
|
35
|
+
Sending signals directly to the worker processes should not normally be
|
|
36
|
+
needed. If the master process is running, any exited worker will be
|
|
37
|
+
automatically respawned.
|
|
38
|
+
|
|
39
|
+
* INT/TERM - Quick shutdown, immediately exit.
|
|
40
|
+
Unless WINCH has been sent to the master (or the master is killed),
|
|
41
|
+
the master process will respawn a worker to replace this one.
|
|
42
|
+
|
|
43
|
+
* QUIT - Gracefully exit after finishing the current request.
|
|
44
|
+
Unless WINCH has been sent to the master (or the master is killed),
|
|
45
|
+
the master process will respawn a worker to replace this one.
|
|
46
|
+
|
|
47
|
+
* USR1 - Reopen all logs owned by the worker process.
|
|
48
|
+
See Unicorn::Util.reopen_logs for what is considered a log.
|
|
49
|
+
Log files are not reopened until it is done processing
|
|
50
|
+
the current request, so multiple log lines for one request
|
|
51
|
+
(as done by Rails) will not be split across multiple logs.
|
|
52
|
+
|
|
53
|
+
=== Procedure to replace a running unicorn executable
|
|
54
|
+
|
|
55
|
+
You may replace a running instance of unicorn with a new one without
|
|
56
|
+
losing any incoming connections. Doing so will reload all of your
|
|
57
|
+
application code, Unicorn config, Ruby executable, and all libraries.
|
|
58
|
+
The only things that will not change (due to OS limitations) are:
|
|
59
|
+
|
|
60
|
+
1. The path to the unicorn executable script. If you want to change to
|
|
61
|
+
a different installation of Ruby, you can modify the shebang
|
|
62
|
+
line to point to your alternative interpreter.
|
|
63
|
+
|
|
64
|
+
The procedure is exactly like that of nginx:
|
|
65
|
+
|
|
66
|
+
1. Send USR2 to the master process
|
|
67
|
+
|
|
68
|
+
2. Check your process manager or pid files to see if a new master spawned
|
|
69
|
+
successfully. If you're using a pid file, the old process will have
|
|
70
|
+
".oldbin" appended to its path. You should have two master instances
|
|
71
|
+
of unicorn running now, both of which will have workers servicing
|
|
72
|
+
requests. Your process tree should look something like this:
|
|
73
|
+
|
|
74
|
+
unicorn master (old)
|
|
75
|
+
\_ unicorn worker[0]
|
|
76
|
+
\_ unicorn worker[1]
|
|
77
|
+
\_ unicorn worker[2]
|
|
78
|
+
\_ unicorn worker[3]
|
|
79
|
+
\_ unicorn master
|
|
80
|
+
\_ unicorn worker[0]
|
|
81
|
+
\_ unicorn worker[1]
|
|
82
|
+
\_ unicorn worker[2]
|
|
83
|
+
\_ unicorn worker[3]
|
|
84
|
+
|
|
85
|
+
3. You can now send WINCH to the old master process so only the new workers
|
|
86
|
+
serve requests. If your unicorn process is bound to an interactive
|
|
87
|
+
terminal, you can skip this step. Step 5 will be more difficult but
|
|
88
|
+
you can also skip it if your process is not daemonized.
|
|
89
|
+
|
|
90
|
+
4. You should now ensure that everything is running correctly with the
|
|
91
|
+
new workers as the old workers die off.
|
|
92
|
+
|
|
93
|
+
5. If everything seems ok, then send QUIT to the old master. You're done!
|
|
94
|
+
|
|
95
|
+
If something is broken, then send HUP to the old master to reload
|
|
96
|
+
the config and restart its workers. Then send QUIT to the new master
|
|
97
|
+
process.
|
data/TODO
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
* Documentation improvements
|
|
2
|
+
|
|
3
|
+
* ensure test suite passes on non-GNU/Linux systems
|
|
4
|
+
(likely that it already does)
|
|
5
|
+
|
|
6
|
+
* consider adding "working_directory" directive to Configurator
|
|
7
|
+
since START_CTX is ugly...
|
|
8
|
+
|
|
9
|
+
* consider adding user switching support (ugh...)
|
|
10
|
+
This makes more sense for Rainbows!, but some folks use it already...
|
|
11
|
+
|
|
12
|
+
* fix const-correctness in HTTP parser
|
|
13
|
+
|
|
14
|
+
* performance validation (esp. TeeInput)
|
|
15
|
+
|
|
16
|
+
* improve test suite (steal from Rainbows!, probably...)
|
data/TUNING
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
= Tuning Unicorn
|
|
2
|
+
|
|
3
|
+
Unicorn performance is generally as good as a (mostly) Ruby web server
|
|
4
|
+
can provide. Most often the performance bottleneck is in the web
|
|
5
|
+
application running on Unicorn rather than Unicorn itself.
|
|
6
|
+
|
|
7
|
+
== Unicorn Configuration
|
|
8
|
+
|
|
9
|
+
See Unicorn::Configurator for details on the config file format.
|
|
10
|
+
|
|
11
|
+
* Setting a very low value for the :backlog parameter in "listen"
|
|
12
|
+
directives can allow failover to happen more quickly if your
|
|
13
|
+
cluster is configured for it.
|
|
14
|
+
|
|
15
|
+
* If you're doing extremely simple benchmarks and getting connection
|
|
16
|
+
errors under high request rates, increasing your :backlog parameter
|
|
17
|
+
above the already-generous default of 1024 can help avoid connection
|
|
18
|
+
errors. Keep in mind this is not recommended for real traffic if
|
|
19
|
+
you have another machine to failover to (see above).
|
|
20
|
+
|
|
21
|
+
* :rcvbuf and :sndbuf parameters generally do not need to be set for TCP
|
|
22
|
+
listeners under Linux 2.6 because auto-tuning is enabled. UNIX domain
|
|
23
|
+
sockets do not have auto-tuning buffer sizes; so increasing those will
|
|
24
|
+
allow syscalls and task switches to be saved for larger requests
|
|
25
|
+
and responses.
|
|
26
|
+
|
|
27
|
+
* Setting "preload_app true" can allow copy-on-write-friendly GC to
|
|
28
|
+
be used to save memory. It will probably not work out of the box with
|
|
29
|
+
applications that open sockets or perform random I/O on files.
|
|
30
|
+
Databases like TokyoCabinet use concurrency-safe pread()/pwrite()
|
|
31
|
+
functions for safe sharing of database file descriptors across
|
|
32
|
+
processes.
|
|
33
|
+
|
|
34
|
+
* On POSIX-compliant filesystems, it is safe for multiple threads or
|
|
35
|
+
processes to append to one log file as long as all the processes are
|
|
36
|
+
have them unbuffered (File#sync = true) or they are
|
|
37
|
+
record(line)-buffered in userspace.
|
|
38
|
+
|
|
39
|
+
* worker_processes should be scaled to the number of processes your
|
|
40
|
+
backend system(s) can support. DO NOT scale it to the number of
|
|
41
|
+
external network clients your application expects to be serving.
|
|
42
|
+
Unicorn is NOT for serving slow clients, that is the job of nginx.
|
|
43
|
+
|
|
44
|
+
== Kernel Parameters (Linux sysctl)
|
|
45
|
+
|
|
46
|
+
WARNING: Do not change system parameters unless you know what you're doing!
|
|
47
|
+
|
|
48
|
+
* net.core.rmem_max and net.core.wmem_max can increase the allowed
|
|
49
|
+
size of :rcvbuf and :sndbuf respectively. This is mostly only useful
|
|
50
|
+
for UNIX domain sockets which do not have auto-tuning buffer sizes.
|
|
51
|
+
|
|
52
|
+
* For load testing/benchmarking with UNIX domain sockets, you should
|
|
53
|
+
consider increasing net.core.somaxconn or else nginx will start
|
|
54
|
+
failing to connect under heavy load. You may also consider setting
|
|
55
|
+
a higher :backlog to listen on as noted earlier.
|
|
56
|
+
|
|
57
|
+
* If you're running out of local ports, consider lowering
|
|
58
|
+
net.ipv4.tcp_fin_timeout to 20-30 (default: 60 seconds). Also
|
|
59
|
+
consider widening the usable port range by changing
|
|
60
|
+
net.ipv4.ip_local_port_range.
|
|
61
|
+
|
|
62
|
+
* Setting net.ipv4.tcp_timestamps=1 will also allow setting
|
|
63
|
+
net.ipv4.tcp_tw_reuse=1 and net.ipv4.tcp_tw_recycle=1, which along
|
|
64
|
+
with the above settings can slow down port exhaustion. Not all
|
|
65
|
+
networks are compatible with these settings, check with your friendly
|
|
66
|
+
network administrator before changing these.
|
|
67
|
+
|
|
68
|
+
* Increasing the MTU size can reduce framing overhead for larger
|
|
69
|
+
transfers. One often-overlooked detail is that the loopback
|
|
70
|
+
device (usually "lo") can have its MTU increased, too.
|
data/bin/unicorn
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
#!/home/ew/bin/ruby
|
|
2
|
+
# -*- encoding: binary -*-
|
|
3
|
+
require 'unicorn/launcher'
|
|
4
|
+
require 'optparse'
|
|
5
|
+
|
|
6
|
+
env = "development"
|
|
7
|
+
daemonize = false
|
|
8
|
+
listeners = []
|
|
9
|
+
options = { :listeners => listeners }
|
|
10
|
+
host, port = Unicorn::Const::DEFAULT_HOST, Unicorn::Const::DEFAULT_PORT
|
|
11
|
+
set_listener = false
|
|
12
|
+
|
|
13
|
+
opts = OptionParser.new("", 24, ' ') do |opts|
|
|
14
|
+
opts.banner = "Usage: #{File.basename($0)} " \
|
|
15
|
+
"[ruby options] [unicorn options] [rackup config file]"
|
|
16
|
+
|
|
17
|
+
opts.separator "Ruby options:"
|
|
18
|
+
|
|
19
|
+
lineno = 1
|
|
20
|
+
opts.on("-e", "--eval LINE", "evaluate a LINE of code") do |line|
|
|
21
|
+
eval line, TOPLEVEL_BINDING, "-e", lineno
|
|
22
|
+
lineno += 1
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
opts.on("-d", "--debug", "set debugging flags (set $DEBUG to true)") do
|
|
26
|
+
$DEBUG = true
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
opts.on("-w", "--warn", "turn warnings on for your script") do
|
|
30
|
+
$-w = true
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
opts.on("-I", "--include PATH",
|
|
34
|
+
"specify $LOAD_PATH (may be used more than once)") do |path|
|
|
35
|
+
$LOAD_PATH.unshift(*path.split(/:/))
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
opts.on("-r", "--require LIBRARY",
|
|
39
|
+
"require the library, before executing your script") do |library|
|
|
40
|
+
require library
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
opts.separator "Unicorn options:"
|
|
44
|
+
|
|
45
|
+
# some of these switches exist for rackup command-line compatibility,
|
|
46
|
+
|
|
47
|
+
opts.on("-o", "--host HOST",
|
|
48
|
+
"listen on HOST (default: #{Unicorn::Const::DEFAULT_HOST})") do |h|
|
|
49
|
+
host = h
|
|
50
|
+
set_listener = true
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
opts.on("-p", "--port PORT",
|
|
54
|
+
"use PORT (default: #{Unicorn::Const::DEFAULT_PORT})") do |p|
|
|
55
|
+
port = p.to_i
|
|
56
|
+
set_listener = true
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
opts.on("-E", "--env ENVIRONMENT",
|
|
60
|
+
"use ENVIRONMENT for defaults (default: development)") do |e|
|
|
61
|
+
env = e
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
opts.on("-D", "--daemonize", "run daemonized in the background") do |d|
|
|
65
|
+
daemonize = d ? true : false
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
opts.on("-P", "--pid FILE", "DEPRECATED") do |f|
|
|
69
|
+
warn %q{Use of --pid/-P is strongly discouraged}
|
|
70
|
+
warn %q{Use the 'pid' directive in the Unicorn config file instead}
|
|
71
|
+
options[:pid] = File.expand_path(f)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
opts.on("-s", "--server SERVER",
|
|
75
|
+
"this flag only exists for compatibility") do |s|
|
|
76
|
+
warn "-s/--server only exists for compatibility with rackup"
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Unicorn-specific stuff
|
|
80
|
+
opts.on("-l", "--listen {HOST:PORT|PATH}",
|
|
81
|
+
"listen on HOST:PORT or PATH",
|
|
82
|
+
"this may be specified multiple times",
|
|
83
|
+
"(default: #{Unicorn::Const::DEFAULT_LISTEN})") do |address|
|
|
84
|
+
listeners << address
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
opts.on("-c", "--config-file FILE", "Unicorn-specific config file") do |f|
|
|
88
|
+
options[:config_file] = File.expand_path(f)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# I'm avoiding Unicorn-specific config options on the command-line.
|
|
92
|
+
# IMNSHO, config options on the command-line are redundant given
|
|
93
|
+
# config files and make things unnecessarily complicated with multiple
|
|
94
|
+
# places to look for a config option.
|
|
95
|
+
|
|
96
|
+
opts.separator "Common options:"
|
|
97
|
+
|
|
98
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
|
99
|
+
puts opts.to_s.gsub(/^.*DEPRECATED.*$/s, '')
|
|
100
|
+
exit
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
opts.on_tail("-v", "--version", "Show version") do
|
|
104
|
+
puts "unicorn v#{Unicorn::Const::UNICORN_VERSION}"
|
|
105
|
+
exit
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
opts.parse! ARGV
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
config = ARGV[0] || "config.ru"
|
|
112
|
+
abort "configuration file #{config} not found" unless File.exist?(config)
|
|
113
|
+
|
|
114
|
+
if config =~ /\.ru$/
|
|
115
|
+
# parse embedded command-line options in config.ru comments
|
|
116
|
+
if File.open(config, "rb") { |fp| fp.sysread(fp.stat.size) } =~ /^#\\(.*)/
|
|
117
|
+
opts.parse! $1.split(/\s+/)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
require 'pp' if $DEBUG
|
|
122
|
+
|
|
123
|
+
app = lambda do ||
|
|
124
|
+
# require Rack as late as possible in case $LOAD_PATH is modified
|
|
125
|
+
# in config.ru or command-line
|
|
126
|
+
inner_app = case config
|
|
127
|
+
when /\.ru$/
|
|
128
|
+
raw = File.open(config, "rb") { |fp| fp.sysread(fp.stat.size) }
|
|
129
|
+
raw.sub!(/^__END__\n.*/, '')
|
|
130
|
+
eval("Rack::Builder.new {(#{raw}\n)}.to_app", nil, config)
|
|
131
|
+
else
|
|
132
|
+
require config
|
|
133
|
+
Object.const_get(File.basename(config, '.rb').capitalize)
|
|
134
|
+
end
|
|
135
|
+
pp({ :inner_app => inner_app }) if $DEBUG
|
|
136
|
+
case env
|
|
137
|
+
when "development"
|
|
138
|
+
Rack::Builder.new do
|
|
139
|
+
use Rack::CommonLogger, $stderr
|
|
140
|
+
use Rack::ShowExceptions
|
|
141
|
+
use Rack::Lint
|
|
142
|
+
run inner_app
|
|
143
|
+
end.to_app
|
|
144
|
+
when "deployment"
|
|
145
|
+
Rack::Builder.new do
|
|
146
|
+
use Rack::CommonLogger, $stderr
|
|
147
|
+
run inner_app
|
|
148
|
+
end.to_app
|
|
149
|
+
else
|
|
150
|
+
inner_app
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
listeners << "#{host}:#{port}" if set_listener
|
|
155
|
+
|
|
156
|
+
if $DEBUG
|
|
157
|
+
pp({
|
|
158
|
+
:unicorn_options => options,
|
|
159
|
+
:app => app,
|
|
160
|
+
:daemonize => daemonize,
|
|
161
|
+
})
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
Unicorn::Launcher.daemonize! if daemonize
|
|
165
|
+
Unicorn.run(app, options)
|
data/bin/unicorn_rails
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
#!/home/ew/bin/ruby
|
|
2
|
+
# -*- encoding: binary -*-
|
|
3
|
+
require 'unicorn/launcher'
|
|
4
|
+
require 'optparse'
|
|
5
|
+
require 'fileutils'
|
|
6
|
+
|
|
7
|
+
rails_pid = "#{Unicorn::HttpServer::START_CTX[:cwd]}/tmp/pids/unicorn.pid"
|
|
8
|
+
cmd = File.basename($0)
|
|
9
|
+
daemonize = false
|
|
10
|
+
listeners = []
|
|
11
|
+
options = { :listeners => listeners }
|
|
12
|
+
host, port = Unicorn::Const::DEFAULT_HOST, Unicorn::Const::DEFAULT_PORT
|
|
13
|
+
set_listener = false
|
|
14
|
+
ENV['RAILS_ENV'] ||= "development"
|
|
15
|
+
|
|
16
|
+
opts = OptionParser.new("", 24, ' ') do |opts|
|
|
17
|
+
opts.banner = "Usage: #{cmd} " \
|
|
18
|
+
"[ruby options] [#{cmd} options] [rackup config file]"
|
|
19
|
+
opts.separator "Ruby options:"
|
|
20
|
+
|
|
21
|
+
lineno = 1
|
|
22
|
+
opts.on("-e", "--eval LINE", "evaluate a LINE of code") do |line|
|
|
23
|
+
eval line, TOPLEVEL_BINDING, "-e", lineno
|
|
24
|
+
lineno += 1
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
opts.on("-d", "--debug", "set debugging flags (set $DEBUG to true)") do
|
|
28
|
+
$DEBUG = true
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
opts.on("-w", "--warn", "turn warnings on for your script") do
|
|
32
|
+
$-w = true
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
opts.on("-I", "--include PATH",
|
|
36
|
+
"specify $LOAD_PATH (may be used more than once)") do |path|
|
|
37
|
+
$LOAD_PATH.unshift(*path.split(/:/))
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
opts.on("-r", "--require LIBRARY",
|
|
41
|
+
"require the library, before executing your script") do |library|
|
|
42
|
+
require library
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
opts.separator "#{cmd} options:"
|
|
46
|
+
|
|
47
|
+
# some of these switches exist for rackup command-line compatibility,
|
|
48
|
+
|
|
49
|
+
opts.on("-o", "--host HOST",
|
|
50
|
+
"listen on HOST (default: #{Unicorn::Const::DEFAULT_HOST})") do |h|
|
|
51
|
+
host = h
|
|
52
|
+
set_listener = true
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
opts.on("-p", "--port PORT", "use PORT (default: #{port})") do |p|
|
|
56
|
+
port = p.to_i
|
|
57
|
+
set_listener = true
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
opts.on("-E", "--env RAILS_ENV",
|
|
61
|
+
"use RAILS_ENV for defaults (default: development)") do |e|
|
|
62
|
+
ENV['RAILS_ENV'] = e
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
opts.on("-D", "--daemonize", "run daemonized in the background") do |d|
|
|
66
|
+
daemonize = d ? true : false
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Unicorn-specific stuff
|
|
70
|
+
opts.on("-l", "--listen {HOST:PORT|PATH}",
|
|
71
|
+
"listen on HOST:PORT or PATH",
|
|
72
|
+
"this may be specified multiple times",
|
|
73
|
+
"(default: #{Unicorn::Const::DEFAULT_LISTEN})") do |address|
|
|
74
|
+
listeners << address
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
opts.on("-c", "--config-file FILE", "Unicorn-specific config file") do |f|
|
|
78
|
+
options[:config_file] = File.expand_path(f)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
opts.on("-P PATH", "DEPRECATED") do |v|
|
|
82
|
+
warn %q{Use of -P is ambiguous and discouraged}
|
|
83
|
+
warn %q{Use --path or RAILS_RELATIVE_URL_ROOT instead}
|
|
84
|
+
ENV['RAILS_RELATIVE_URL_ROOT'] = v
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
opts.on("--path PATH", "Runs Rails app mounted at a specific path.",
|
|
88
|
+
"(default: /)") do |v|
|
|
89
|
+
ENV['RAILS_RELATIVE_URL_ROOT'] = v
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# I'm avoiding Unicorn-specific config options on the command-line.
|
|
93
|
+
# IMNSHO, config options on the command-line are redundant given
|
|
94
|
+
# config files and make things unnecessarily complicated with multiple
|
|
95
|
+
# places to look for a config option.
|
|
96
|
+
|
|
97
|
+
opts.separator "Common options:"
|
|
98
|
+
|
|
99
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
|
100
|
+
puts opts.to_s.gsub(/^.*DEPRECATED.*$/s, '')
|
|
101
|
+
exit
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
opts.on_tail("-v", "--version", "Show version") do
|
|
105
|
+
puts " v#{Unicorn::Const::UNICORN_VERSION}"
|
|
106
|
+
exit
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
opts.parse! ARGV
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
config = ARGV[0] || (File.exist?('config.ru') ? 'config.ru' : nil)
|
|
113
|
+
|
|
114
|
+
if config && config =~ /\.ru$/
|
|
115
|
+
# parse embedded command-line options in config.ru comments
|
|
116
|
+
if File.open(config, "rb") { |fp| fp.sysread(fp.stat.size) } =~ /^#\\(.*)/
|
|
117
|
+
opts.parse! $1.split(/\s+/)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
require 'pp' if $DEBUG
|
|
122
|
+
|
|
123
|
+
# this won't run until after forking if preload_app is false
|
|
124
|
+
app = lambda do ||
|
|
125
|
+
# Load Rails and the private version of Rack it bundles.
|
|
126
|
+
begin
|
|
127
|
+
require 'config/boot'
|
|
128
|
+
rescue LoadError => err
|
|
129
|
+
abort "#$0 must be run inside RAILS_ROOT: #{err.inspect}"
|
|
130
|
+
end
|
|
131
|
+
defined?(::RAILS_ROOT) or abort "RAILS_ROOT not defined by config/boot"
|
|
132
|
+
defined?(::RAILS_ENV) or abort "RAILS_ENV not defined by config/boot"
|
|
133
|
+
defined?(::Rails::VERSION::STRING) or
|
|
134
|
+
abort "Rails::VERSION::STRING not defined by config/boot"
|
|
135
|
+
|
|
136
|
+
inner_app = case config
|
|
137
|
+
when nil
|
|
138
|
+
require 'config/environment'
|
|
139
|
+
|
|
140
|
+
# it seems Rails >=2.2 support Rack, but only >=2.3 requires it
|
|
141
|
+
old_rails = case ::Rails::VERSION::MAJOR
|
|
142
|
+
when 0, 1 then true
|
|
143
|
+
when 2 then Rails::VERSION::MINOR < 3 ? true : false
|
|
144
|
+
else
|
|
145
|
+
false
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
if old_rails
|
|
149
|
+
require 'unicorn/app/old_rails'
|
|
150
|
+
Unicorn::App::OldRails.new
|
|
151
|
+
else
|
|
152
|
+
ActionController::Dispatcher.new
|
|
153
|
+
end
|
|
154
|
+
when /\.ru$/
|
|
155
|
+
raw = File.open(config, "rb") { |fp| fp.sysread(fp.stat.size) }
|
|
156
|
+
raw.sub!(/^__END__\n.*/, '')
|
|
157
|
+
eval("Rack::Builder.new {(#{raw}\n)}.to_app", nil, config)
|
|
158
|
+
else
|
|
159
|
+
require config
|
|
160
|
+
Object.const_get(File.basename(config, '.rb').capitalize)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
Rack::Builder.new do
|
|
164
|
+
map_path = ENV['RAILS_RELATIVE_URL_ROOT'] || '/'
|
|
165
|
+
if inner_app.class.to_s == "Unicorn::App::OldRails"
|
|
166
|
+
if map_path != '/'
|
|
167
|
+
# patches + tests welcome, but I really cbf to deal with this
|
|
168
|
+
# since all apps I've ever dealt with just use "/" ...
|
|
169
|
+
$stderr.puts "relative URL roots may not work for older Rails"
|
|
170
|
+
end
|
|
171
|
+
$stderr.puts "LogTailer not available for Rails < 2.3" unless daemonize
|
|
172
|
+
$stderr.puts "Debugger not available" if $DEBUG
|
|
173
|
+
map(map_path) do
|
|
174
|
+
require 'unicorn/app/old_rails/static'
|
|
175
|
+
use Unicorn::App::OldRails::Static
|
|
176
|
+
run inner_app
|
|
177
|
+
end
|
|
178
|
+
else
|
|
179
|
+
use Rails::Rack::LogTailer unless daemonize
|
|
180
|
+
use Rails::Rack::Debugger if $DEBUG
|
|
181
|
+
map(map_path) do
|
|
182
|
+
use Rails::Rack::Static
|
|
183
|
+
run inner_app
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end.to_app
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
listeners << "#{host}:#{port}" if set_listener
|
|
190
|
+
|
|
191
|
+
if $DEBUG
|
|
192
|
+
pp({
|
|
193
|
+
:unicorn_options => options,
|
|
194
|
+
:app => app,
|
|
195
|
+
:daemonize => daemonize,
|
|
196
|
+
})
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# ensure Rails standard tmp paths exist
|
|
200
|
+
%w(cache pids sessions sockets).each do |dir|
|
|
201
|
+
FileUtils.mkdir_p("tmp/#{dir}")
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
if daemonize
|
|
205
|
+
options[:pid] = rails_pid
|
|
206
|
+
Unicorn::Launcher.daemonize!
|
|
207
|
+
end
|
|
208
|
+
Unicorn.run(app, options)
|