scgi 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/{COPYING → LICENSE} +0 -0
- data/README +21 -203
- data/lib/scgi.rb +7 -19
- metadata +5 -6
- data/bin/scgi_ctrl +0 -236
- data/lib/RailsSCGIProcessor.rb +0 -28
data/{COPYING → LICENSE}
RENAMED
File without changes
|
data/README
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
= ruby-scgi
|
2
2
|
|
3
|
-
ruby-scgi is a
|
3
|
+
ruby-scgi is a Ruby library for running Ruby on Rails (and possibly other
|
4
4
|
web applications) for high-speed deployment of your applications in production.
|
5
5
|
It is intended as a replacement for the ancient FastCGI code base and bring
|
6
6
|
some big advantages to Rails deployment for production operations.
|
@@ -21,29 +21,17 @@ Subversion access is available at svn://code.jeremyevans.net/ruby-scgi/.
|
|
21
21
|
|
22
22
|
== Advantages
|
23
23
|
|
24
|
-
* Simultaneous support for Apache1, Apache2, and lighttpd on OSX and most
|
25
|
-
Linux/BSD systems.
|
26
24
|
* Same performance as FastCGI and better performance than other methods.
|
27
|
-
*
|
28
|
-
*
|
29
|
-
extra boost in concurrency.
|
30
|
-
* Supports both command line and config file configuration.
|
31
|
-
* Gives out limited status information to help manage your Rails application's
|
25
|
+
* Can be used to run Rails with style (sudo gem install style)
|
26
|
+
* Gives out limited status information to help manage your application's
|
32
27
|
resources.
|
33
|
-
* Makes it easy to manage your production deployment, and you can even run your
|
34
|
-
application in development mode exactly the same way as with script/server
|
35
|
-
for extra testing efficiency.
|
36
28
|
* You can set a maximum concurrent connections limit, which causes any
|
37
29
|
connections over the limit to get redirected to a /busy.html file. This can
|
38
30
|
help keep your site alive under heavy load.
|
39
|
-
* Simple to configure with your web server.
|
40
|
-
be able to manage your webserver and Rails application independently.
|
41
|
-
* Supports supervisor mode for rock solid upgrades without losing connections
|
42
|
-
* Reasonable defaults for almost everything based on user feedback.
|
31
|
+
* Simple to configure with your web server.
|
43
32
|
* Completely free code licensed under Rails's own license.
|
44
33
|
* No external dependencies other than Ruby
|
45
|
-
* The core implementation
|
46
|
-
other Ruby web frameworks.
|
34
|
+
* The core implementation is easily extensible for other Ruby web frameworks.
|
47
35
|
|
48
36
|
== Comparison With FastCGI
|
49
37
|
|
@@ -85,162 +73,16 @@ ruby-scgi on a totally different machine with this.
|
|
85
73
|
|
86
74
|
== Running and Configuration
|
87
75
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
To stop the application:
|
93
|
-
|
94
|
-
scgi_ctrl -d /path/to/rails/app stop
|
95
|
-
|
96
|
-
To restart the application:
|
97
|
-
|
98
|
-
scgi_ctrl -d /path/to/rails/app restart
|
99
|
-
|
100
|
-
Note that restarting/stopping is controlled by a pid file (the location is
|
101
|
-
configurable). If the pidfile exists, it is read and the pids in it are
|
102
|
-
killed. If restarting, new processes are forked after the existing processes
|
103
|
-
are killed.
|
104
|
-
|
105
|
-
To see the possible and default configuration options, just run the program
|
106
|
-
without any arguments:
|
107
|
-
|
108
|
-
scgi_ctrl [option=value, ...] (start|stop)
|
109
|
-
Options:
|
110
|
-
-b, --bind IP address to bind to [127.0.0.1]
|
111
|
-
-c, --config Location of config file [config/scgi.yaml]
|
112
|
-
-d, --directory Working directory [.]
|
113
|
-
-e, --environment Environment (for Rails) [production]
|
114
|
-
-f, --fork Number of listners on each port [1]
|
115
|
-
-k, --killtime Number of seconds to wait when killing children [2]
|
116
|
-
-l, --logfile Location of log file [log/scgi.log]
|
117
|
-
-m, --maxconns Maximum number of concurrent users [2**30-1]
|
118
|
-
-n, --number Number of ports to bind to [1]
|
119
|
-
-p, --port Starting port to bind to [9999]
|
120
|
-
-P, --pidfile Location of pid file [log/scgi.pid]
|
121
|
-
-r, --processor Type of processor to use [Rails]
|
122
|
-
-s, --supervise Whether to use a supervisor [No]
|
123
|
-
|
124
|
-
Note that the -d (--directory) option changes the working directory of the
|
125
|
-
process, so the -c, -l, and -P options are relative to that.
|
126
|
-
|
127
|
-
Here's a longer explanation of the options:
|
128
|
-
|
129
|
-
-b, --bind IP address to bind to [127.0.0.1]
|
130
|
-
|
131
|
-
This is the TCP/IP networking sockets to bind to. It defaults to the
|
132
|
-
loopback address because generally the web application runs on the same
|
133
|
-
physical server as the web server. If this is not the case, change it to an
|
134
|
-
externally available IP, and make sure to lock down access to the port via a
|
135
|
-
firewall.
|
136
|
-
|
137
|
-
-c, --config Location of config file [config/scgi.yaml]
|
138
|
-
|
139
|
-
This is the configuration file for ruby-scgi. It is recommended that you use
|
140
|
-
this instead of the command line configuration, as it saves typing. This
|
141
|
-
path is relative to the working directory, so if it is not inside the working
|
142
|
-
directory, make sure you specify an absolute path. Also, note that this is
|
143
|
-
the only option that is not configurable from the configuration file.
|
144
|
-
|
145
|
-
-d, --directory Working directory [.]
|
146
|
-
|
147
|
-
This is the working directory of the process. It should generally be the
|
148
|
-
path to the root of the web application. Alternatively, you can change to
|
149
|
-
the root of the web application before hand and then not use this option.
|
150
|
-
|
151
|
-
-e, --environment Environment (for Rails) [production]
|
152
|
-
|
153
|
-
This is the only option that is Rails-specific, allowing you to specify the
|
154
|
-
Rails environment on the command line. It defaults to production because
|
155
|
-
that is the general use case for ruby-scgi.
|
156
|
-
|
157
|
-
-f, --fork Number of listners on each port [1]
|
158
|
-
|
159
|
-
This enables single-port clustering of processes, so there are multiple
|
160
|
-
processes listening on each port. This can simplify configuration of the
|
161
|
-
webserver, since only a single port need be specified, and can also eliminate
|
162
|
-
the need for a proxy such as pound or pen to handle this for you. It
|
163
|
-
defaults to one process per port. Try single port clustering first, and if
|
164
|
-
it is not stable, switch to multiple port clustering. It is possible to use
|
165
|
-
both as once.
|
166
|
-
|
167
|
-
-k, --killtime Number of seconds to wait when killing children [2]
|
168
|
-
|
169
|
-
This sets the time that ruby-scgi will wait when stopping or restarting
|
170
|
-
child processes. The time can actually be twice as long as this, if the
|
171
|
-
child processes are not shutting down cleanly.
|
172
|
-
|
173
|
-
-l, --logfile Location of log file [log/scgi.log]
|
174
|
-
|
175
|
-
This is the location of the log file, relative to the working directory.
|
176
|
-
ruby-scgi doesn't log all that much (starts, shutdowns, bad requests, other
|
177
|
-
errors, and status info when sent SIGUSR2).
|
178
|
-
|
179
|
-
-m, --maxconns Maximum number of concurrent users [2**30-1]
|
180
|
-
|
181
|
-
The maximum number of concurrent connections. If more connections that this
|
182
|
-
are sent to the server, it redirects them to the /busy.html file.
|
183
|
-
|
184
|
-
-n, --number Number of ports to bind to [1]
|
185
|
-
|
186
|
-
This enables multi-port clustering. Multi-port clustering listens on
|
187
|
-
multiple ports starting with the port specified (so port, port+1, port+2,
|
188
|
-
...). This makes webserver configuration a little more difficult, and might
|
189
|
-
also require a separate proxy such as pound or pen, so you should try
|
190
|
-
single-port clustering first. You can run both at once if you want.
|
191
|
-
|
192
|
-
-p, --port Starting port to bind to [9999]
|
193
|
-
|
194
|
-
This is the starting (or only) port that ruby-scgi will use. If multi-port
|
195
|
-
clustering is used, all ports will be greater than this one.
|
196
|
-
|
197
|
-
-P, --pidfile Location of pid file [log/scgi.pid]
|
198
|
-
|
199
|
-
This is the pid file, relative to the working directory. The pid file is
|
200
|
-
necessary, as it is what is used to specify which pids to kill when stopping
|
201
|
-
or restarting. If incorrect information is in the pid file, the processes
|
202
|
-
won't be stopped when they should be, and you will probably won't be able
|
203
|
-
to start new processes (because the ports will still be in use).
|
204
|
-
|
205
|
-
-r, --processor Type of processor to use [Rails]
|
206
|
-
|
207
|
-
This is the type of processor to use, it defaults to Rails, as that is the
|
208
|
-
only one currently supported. Adding other processers is fairly easy, just
|
209
|
-
make the processor is in a file named XXXXXSCGIProcessor.rb (where XXXXX is
|
210
|
-
in the name of the processor), and that file is located in ruby's library
|
211
|
-
path (the RUBYLIB environment variable). See RailsSCGIProcessor.rb for an
|
212
|
-
example.
|
213
|
-
|
214
|
-
-s, --supervise Whether to use a supervisor [No]
|
215
|
-
|
216
|
-
This starts a supervisor process in addition to the worker processes. The
|
217
|
-
supervisor process can then add and remove children using the same SCGI
|
218
|
-
listening socket, which means that there will be no downtime when you have
|
219
|
-
to upgrade your application. Using a supervisor restricts some of the
|
220
|
-
variables that will be updated when you use restart. You can change the
|
221
|
-
environment, fork, killtime, logfile, maxconns, and processor variables.
|
222
|
-
Note that if you use a supervisor, you should specify those variables in
|
223
|
-
the config file and not on the command line, otherwise it won't be
|
224
|
-
possible to update them. This is the only option that does not take an
|
225
|
-
argument on the command line. To set it in the config file, see below.
|
226
|
-
|
227
|
-
Each of the options can also be specified in the config file as a symbol. An
|
228
|
-
example config file would be:
|
229
|
-
|
230
|
-
---
|
231
|
-
:port: 4000
|
232
|
-
:fork: 3
|
233
|
-
:supervise: true
|
234
|
-
|
235
|
-
This sets up a supervised single-port cluster on port 4000 with 3 listening
|
236
|
-
processes.
|
76
|
+
ruby-scgi is now just a library and doesn't come with a tool to run Rails. The
|
77
|
+
previous command line tool (scgi_ctrl) has been greatly enhanced and is now
|
78
|
+
available as a standalone gem called style.
|
237
79
|
|
238
80
|
== Example configurations
|
239
81
|
|
240
82
|
Note that ruby-scgi is only tested on Lighttpd. Also, note that Lighttpd
|
241
83
|
1.4.16 has a bug which breaks redirects using server.error-handler-404, so
|
242
|
-
either use mod_magnet,
|
243
|
-
|
84
|
+
either use mod_magnet, use 1.4.17, or apply the patch in ticket 1270 on
|
85
|
+
Lighttpd's Trac.
|
244
86
|
|
245
87
|
Lighttpd:
|
246
88
|
|
@@ -299,28 +141,14 @@ Apache:
|
|
299
141
|
</Directory>
|
300
142
|
</VirtualHost>
|
301
143
|
|
302
|
-
==
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
then you should use something else or find a better provider.
|
311
|
-
* The config file, pid file, and log file and directories should have
|
312
|
-
appropriate permissions. The config file should ideally be readable but not
|
313
|
-
writable by the user running scgi_ctrl. The pid and log file directory
|
314
|
-
should be writable by the user running scgi_ctrl and by no other user. If
|
315
|
-
the config file is writable by a non-trusted user, they could potentially
|
316
|
-
run arbitrary code, and they could certainly open arbitrary ports and or
|
317
|
-
attempt denial of service. If the pid file is writable by a non-trusted
|
318
|
-
user, it could cause arbitrary processes to be killed by the user running
|
319
|
-
scgi_ctrl
|
320
|
-
* Never run scgi_ctrl as root. If you don't know why you should read up about
|
321
|
-
the unix security model before deploying any more software.
|
322
|
-
|
323
|
-
== Changes from previous versions
|
144
|
+
== Changes from version 0.7.0
|
145
|
+
|
146
|
+
* Command line tool is now in a seperate gem called style
|
147
|
+
* You now must pass a socket to SCGI::Processor#listen
|
148
|
+
* SCGI::Processor's @log and @maxconns now have defaults
|
149
|
+
* SCGI::Processor's @host and @port are no longer used
|
150
|
+
|
151
|
+
== Changes from SCGI Rails Runner by Zed Shaw
|
324
152
|
|
325
153
|
* Single-port clustering is back
|
326
154
|
* scgi_ctrl is fully configurable on the command line
|
@@ -337,16 +165,6 @@ the new hotness!
|
|
337
165
|
|
338
166
|
A: Well, aren't you snotty. You can certainly use Mongrel if you want. The
|
339
167
|
memory/performance differences are small, and it is probably better maintained.
|
340
|
-
ruby-scgi
|
341
|
-
setups. Also, it works well and it's been working for me for
|
342
|
-
years, so I haven't felt the need to change.
|
343
|
-
|
344
|
-
Q: Does it work with Capistrano yet?
|
345
|
-
|
346
|
-
A: I haven't tried. If you have luck, let me know.
|
347
|
-
|
348
|
-
Q: Is there an easy way to reload? I don't want to take the whole thing down
|
349
|
-
just to deploy new code.
|
350
|
-
|
351
|
-
A: Use supervise mode, which ensures that no connections will be lost when
|
352
|
-
updating your apps.
|
168
|
+
ruby-scgi is a simpler version of SCGI Rails Runner, and may be useful for
|
169
|
+
certain legacy setups. Also, it works well and it's been working for me for
|
170
|
+
the last few years, so I haven't felt the need to change to Mongrel.
|
data/lib/scgi.rb
CHANGED
@@ -82,32 +82,21 @@ module SCGI
|
|
82
82
|
# they aren't supported in Apache, and in lighttpd they're unreliable.
|
83
83
|
# Also, domain sockets don't work so well on Windows.
|
84
84
|
class Processor < Monitor
|
85
|
-
attr_reader :settings
|
86
|
-
|
87
85
|
def initialize(settings = {})
|
88
86
|
@total_conns = 0
|
89
87
|
@shutdown = false
|
90
88
|
@dead = false
|
91
89
|
@threads = Queue.new
|
92
|
-
@
|
93
|
-
@
|
94
|
-
@host = settings[:bind]
|
95
|
-
@port = settings[:port]
|
96
|
-
@maxconns = settings[:maxconns]
|
90
|
+
@log = LogFactory.instance.create(settings[:logfile] || 'log/scgi.log')
|
91
|
+
@maxconns = settings[:maxconns] || 2**30-1
|
97
92
|
super()
|
98
93
|
setup_signals
|
99
94
|
end
|
100
95
|
|
101
|
-
# Starts the SCGI::Processor having it listen on
|
102
|
-
#
|
103
|
-
|
104
|
-
|
105
|
-
# to listen to it.
|
106
|
-
#
|
107
|
-
# This function does not return until a shutdown.
|
108
|
-
def listen(socket = nil)
|
109
|
-
@log.info("Started listening on #{@host}:#{@port} at #{@started = Time.now}")
|
110
|
-
@socket = socket || TCPServer.new(@host, @port)
|
96
|
+
# Starts the SCGI::Processor having it listen on the given socket. This
|
97
|
+
# function does not return until a shutdown.
|
98
|
+
def listen(socket)
|
99
|
+
@socket = socket
|
111
100
|
|
112
101
|
# we also need a small collector thread that does nothing
|
113
102
|
# but pull threads off the thread queue and joins them
|
@@ -237,8 +226,7 @@ module SCGI
|
|
237
226
|
# when dumping data to the logs
|
238
227
|
def status_info
|
239
228
|
{
|
240
|
-
:time => Time.now, :pid => Process.pid, :
|
241
|
-
:environment => @settings[:environment], :started => @started,
|
229
|
+
:time => Time.now, :pid => Process.pid, :started => @started,
|
242
230
|
:max_conns => @maxconns, :conns => @threads.length, :systimes => Process.times,
|
243
231
|
:shutdown => @shutdown, :dead => @dead, :total_conns => @total_conns
|
244
232
|
}.inspect
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
|
|
3
3
|
specification_version: 1
|
4
4
|
name: scgi
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2007-
|
6
|
+
version: 0.8.0
|
7
|
+
date: 2007-09-06 00:00:00 -07:00
|
8
8
|
summary: Simple support for using SCGI in ruby apps, such as Rails
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -29,10 +29,9 @@ post_install_message:
|
|
29
29
|
authors:
|
30
30
|
- Jeremy Evans
|
31
31
|
files:
|
32
|
-
-
|
32
|
+
- LICENSE
|
33
33
|
- README
|
34
34
|
- lib/scgi.rb
|
35
|
-
- lib/RailsSCGIProcessor.rb
|
36
35
|
test_files: []
|
37
36
|
|
38
37
|
rdoc_options:
|
@@ -40,8 +39,8 @@ rdoc_options:
|
|
40
39
|
- --line-numbers
|
41
40
|
extra_rdoc_files: []
|
42
41
|
|
43
|
-
executables:
|
44
|
-
|
42
|
+
executables: []
|
43
|
+
|
45
44
|
extensions: []
|
46
45
|
|
47
46
|
requirements: []
|
data/bin/scgi_ctrl
DELETED
@@ -1,236 +0,0 @@
|
|
1
|
-
#!/usr/local/bin/ruby
|
2
|
-
require 'getoptlong'
|
3
|
-
require 'yaml'
|
4
|
-
require 'socket'
|
5
|
-
SCGI_DEFAULT_CONFIG = {:pidfile=>'log/scgi.pid', :number=>1, :port=>9999,
|
6
|
-
:processor=>'Rails', :fork=>1, :logfile=>'log/scgi.log', :maxconns=>2**30-1,
|
7
|
-
:bind=>'127.0.0.1', :cliconfig=>{}, :killtime=>2, :config=>'config/scgi.yaml'}
|
8
|
-
SCGI_CONFIG = {}
|
9
|
-
|
10
|
-
module SCGI
|
11
|
-
class Starter
|
12
|
-
def initialize
|
13
|
-
super
|
14
|
-
parse_options
|
15
|
-
end
|
16
|
-
|
17
|
-
def config_file_options(filename)
|
18
|
-
begin
|
19
|
-
config = YAML.load(File.read(filename))
|
20
|
-
config.is_a?(Hash) ? config : Hash.new
|
21
|
-
rescue
|
22
|
-
Hash.new
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def get_processor(string)
|
27
|
-
raise NameError, "#{string} is not a valid processor!" unless string =~ /\A[A-Z][A-ZA-z]*\z/
|
28
|
-
processor = "#{string}SCGIProcessor"
|
29
|
-
require processor
|
30
|
-
eval(processor)
|
31
|
-
end
|
32
|
-
|
33
|
-
def kill_children_forcefully(pids)
|
34
|
-
kill_pids('TERM', *pids)
|
35
|
-
sleep(SCGI_CONFIG[:killtime])
|
36
|
-
kill_pids('KILL', *pids)
|
37
|
-
end
|
38
|
-
|
39
|
-
def kill_children_gently(pids)
|
40
|
-
kill_pids('INT', *pids)
|
41
|
-
sleep(SCGI_CONFIG[:killtime])
|
42
|
-
sleep(SCGI_CONFIG[:killtime]) if kill_pids('TERM', *pids)
|
43
|
-
kill_pids('KILL', *pids)
|
44
|
-
end
|
45
|
-
|
46
|
-
def kill_pids(signal, *pids)
|
47
|
-
Process.kill(signal, *pids) rescue nil
|
48
|
-
end
|
49
|
-
|
50
|
-
def parse_options
|
51
|
-
cliconfig = {}
|
52
|
-
opts = GetoptLong.new(
|
53
|
-
[ '--bind', '-b', GetoptLong::REQUIRED_ARGUMENT ],
|
54
|
-
[ '--config', '-c', GetoptLong::REQUIRED_ARGUMENT ],
|
55
|
-
[ '--directory', '-d', GetoptLong::REQUIRED_ARGUMENT ],
|
56
|
-
[ '--environment', '-e', GetoptLong::REQUIRED_ARGUMENT ],
|
57
|
-
[ '--fork', '-f', GetoptLong::REQUIRED_ARGUMENT ],
|
58
|
-
[ '--killtime', '-k', GetoptLong::REQUIRED_ARGUMENT ],
|
59
|
-
[ '--logfile', '-l', GetoptLong::REQUIRED_ARGUMENT ],
|
60
|
-
[ '--maxconns', '-m', GetoptLong::REQUIRED_ARGUMENT ],
|
61
|
-
[ '--number', '-n', GetoptLong::REQUIRED_ARGUMENT ],
|
62
|
-
[ '--port', '-p', GetoptLong::REQUIRED_ARGUMENT ],
|
63
|
-
[ '--pidfile', '-P', GetoptLong::REQUIRED_ARGUMENT ],
|
64
|
-
[ '--processor', '-r', GetoptLong::REQUIRED_ARGUMENT ],
|
65
|
-
[ '--supervise', '-s', GetoptLong::NO_ARGUMENT]
|
66
|
-
)
|
67
|
-
opts.each do |opt, arg|
|
68
|
-
case opt
|
69
|
-
when '--bind'
|
70
|
-
cliconfig[:bind] = arg
|
71
|
-
when '--config'
|
72
|
-
cliconfig[:config] = arg
|
73
|
-
when '--directory'
|
74
|
-
Dir.chdir(arg)
|
75
|
-
when '--environment'
|
76
|
-
cliconfig[:environment] = arg
|
77
|
-
when '--fork'
|
78
|
-
cliconfig[:fork] = arg.to_i
|
79
|
-
when '--killtime'
|
80
|
-
cliconfig[:killtime] = arg.to_i
|
81
|
-
when '--logfile'
|
82
|
-
cliconfig[:logile] = arg
|
83
|
-
when '--maxconns'
|
84
|
-
cliconfig[:maxconns] = arg.to_i
|
85
|
-
when '--number'
|
86
|
-
cliconfig[:number] = arg.to_i
|
87
|
-
when '--port'
|
88
|
-
cliconfig[:port] = arg.to_i
|
89
|
-
when '--pidfile'
|
90
|
-
cliconfig[:pidfile] = arg
|
91
|
-
when '--processor'
|
92
|
-
cliconfig[:processor] = arg
|
93
|
-
when '--supervise'
|
94
|
-
cliconfig[:supervise] = true
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
# Configuration Precedence: Command Line > Config File > Default
|
99
|
-
SCGI_CONFIG.merge!(SCGI_DEFAULT_CONFIG)
|
100
|
-
SCGI_CONFIG.merge!(config_file_options(cliconfig[:config] || SCGI_DEFAULT_CONFIG[:config]))
|
101
|
-
SCGI_CONFIG.merge!(cliconfig)
|
102
|
-
SCGI_CONFIG[:cliconfig] = cliconfig
|
103
|
-
end
|
104
|
-
|
105
|
-
def process(command)
|
106
|
-
return process_supervisor(command) if SCGI_CONFIG[:supervise]
|
107
|
-
case command
|
108
|
-
when 'restart'
|
109
|
-
stop
|
110
|
-
start
|
111
|
-
when 'start'
|
112
|
-
start
|
113
|
-
when 'stop'
|
114
|
-
stop
|
115
|
-
else
|
116
|
-
puts usage
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
def process_supervisor(command)
|
121
|
-
case command
|
122
|
-
when 'restart'
|
123
|
-
supervisor_restart
|
124
|
-
when 'start'
|
125
|
-
supervisor_start
|
126
|
-
when 'stop'
|
127
|
-
supervisor_stop
|
128
|
-
else
|
129
|
-
puts usage
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
def reload_config
|
134
|
-
SCGI_CONFIG.merge!(config_file_options(SCGI_CONFIG[:config]))
|
135
|
-
SCGI_CONFIG.merge!(SCGI_CONFIG[:cliconfig])
|
136
|
-
end
|
137
|
-
|
138
|
-
def start_child(socket, port)
|
139
|
-
fork do
|
140
|
-
$0 = "scgi-#{SCGI_CONFIG[:processor]} dir:#{Dir.pwd} port:#{port}"
|
141
|
-
get_processor(SCGI_CONFIG[:processor]).new(SCGI_CONFIG).listen(socket)
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
def start
|
146
|
-
pids = []
|
147
|
-
SCGI_CONFIG[:number].times do |i|
|
148
|
-
socket = TCPServer.new(SCGI_CONFIG[:bind], port = SCGI_CONFIG[:port]+i)
|
149
|
-
SCGI_CONFIG[:fork].times do
|
150
|
-
pids << start_child(socket, port)
|
151
|
-
end
|
152
|
-
end
|
153
|
-
File.open(SCGI_CONFIG[:pidfile], 'wb'){|file| file.print("#{pids.join(' ')}")}
|
154
|
-
end
|
155
|
-
|
156
|
-
def stop
|
157
|
-
if File.file?(SCGI_CONFIG[:pidfile])
|
158
|
-
pids = nil
|
159
|
-
File.open(SCGI_CONFIG[:pidfile], 'rb'){|f| pids = f.read.split.collect{|x| x.to_i if x.to_i > 0}.compact}
|
160
|
-
if pids.length > 0
|
161
|
-
kill_children_gently(pids)
|
162
|
-
File.delete(SCGI_CONFIG[:pidfile])
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
def supervisor_exit
|
168
|
-
File.delete(SCGI_CONFIG[:pidfile])
|
169
|
-
exit
|
170
|
-
end
|
171
|
-
|
172
|
-
def supervisor_loop
|
173
|
-
$0 = "scgi-#{SCGI_CONFIG[:processor]} dir:#{Dir.pwd} supervisor"
|
174
|
-
trap("HUP") { reload_config; supervisor_restart_children }
|
175
|
-
trap("TERM") { kill_children_forcefully(SCGI_CONFIG[:pids].values.flatten); supervisor_exit }
|
176
|
-
trap("INT") { kill_children_gently(SCGI_CONFIG[:pids].values.flatten); supervisor_exit }
|
177
|
-
loop{sleep(60)}
|
178
|
-
end
|
179
|
-
|
180
|
-
def supervisor_restart
|
181
|
-
kill_pids("HUP", File.read(SCGI_CONFIG[:pidfile]).to_i)
|
182
|
-
end
|
183
|
-
|
184
|
-
def supervisor_restart_children
|
185
|
-
new_pids = {}
|
186
|
-
SCGI_CONFIG[:pids].each do |port, pids|
|
187
|
-
SCGI_CONFIG[:fork].times do
|
188
|
-
(new_pids[port] ||= []) << start_child(SCGI_CONFIG[:sockets][port], port)
|
189
|
-
end
|
190
|
-
kill_children_gently(pids)
|
191
|
-
pids.each{|pid| Process.detach(pid)}
|
192
|
-
end
|
193
|
-
SCGI_CONFIG[:pids] = new_pids
|
194
|
-
end
|
195
|
-
|
196
|
-
def supervisor_start
|
197
|
-
SCGI_CONFIG[:pids] = {}
|
198
|
-
SCGI_CONFIG[:sockets] = {}
|
199
|
-
SCGI_CONFIG[:number].times do |i|
|
200
|
-
port = SCGI_CONFIG[:port]+i
|
201
|
-
SCGI_CONFIG[:sockets][port] = TCPServer.new(SCGI_CONFIG[:bind], port)
|
202
|
-
SCGI_CONFIG[:fork].times do
|
203
|
-
(SCGI_CONFIG[:pids][port] ||= []) << start_child(SCGI_CONFIG[:sockets][port], port)
|
204
|
-
end
|
205
|
-
end
|
206
|
-
File.open(SCGI_CONFIG[:pidfile], 'wb'){|file| file.print(fork{supervisor_loop})}
|
207
|
-
end
|
208
|
-
|
209
|
-
def supervisor_stop
|
210
|
-
kill_pids("INT", File.read(SCGI_CONFIG[:pidfile]).to_i)
|
211
|
-
end
|
212
|
-
|
213
|
-
def usage
|
214
|
-
<<-END
|
215
|
-
scgi_ctrl [option value, ...] (restart|start|stop)
|
216
|
-
Options:
|
217
|
-
-b, --bind IP address to bind to [127.0.0.1]
|
218
|
-
-c, --config Location of config file [config/scgi.yaml]
|
219
|
-
-d, --directory Working directory [.]
|
220
|
-
-e, --environment Environment (for Rails) [production]
|
221
|
-
-f, --fork Number of listners on each port [1]
|
222
|
-
-k, --killtime Number of seconds to wait when killing children [2]
|
223
|
-
-l, --logfile Location of log file [log/scgi.log]
|
224
|
-
-m, --maxconns Maximum number of concurrent users [2**30-1]
|
225
|
-
-n, --number Number of ports to bind to [1]
|
226
|
-
-p, --port Starting port to bind to [9999]
|
227
|
-
-P, --pidfile Location of pid file [log/scgi.pid]
|
228
|
-
-r, --processor Type of processor to use [Rails]
|
229
|
-
-s, --supervise Whether to use a supervisor [No]
|
230
|
-
END
|
231
|
-
end
|
232
|
-
end
|
233
|
-
end
|
234
|
-
|
235
|
-
SCGI::Starter.new.process(ARGV[0])
|
236
|
-
|
data/lib/RailsSCGIProcessor.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
#!/usr/local/bin/ruby
|
2
|
-
require 'scgi'
|
3
|
-
|
4
|
-
# This SCGI::Processor subclass hooks the SCGI request into Ruby on Rails.
|
5
|
-
class RailsSCGIProcessor < SCGI::Processor
|
6
|
-
# Initialzes Rails with the appropriate environment and settings
|
7
|
-
def initialize(settings)
|
8
|
-
ENV["RAILS_ENV"] = settings[:environment] || 'production'
|
9
|
-
require "config/environment"
|
10
|
-
ActiveRecord::Base.threaded_connections = false
|
11
|
-
require 'dispatcher'
|
12
|
-
super(settings)
|
13
|
-
@guard = Mutex.new
|
14
|
-
end
|
15
|
-
|
16
|
-
# Submits requests to Rails in a single threaded fashion
|
17
|
-
def process_request(request, body, socket)
|
18
|
-
return if socket.closed?
|
19
|
-
cgi = SCGI::CGIFixed.new(request, body, socket)
|
20
|
-
begin
|
21
|
-
@guard.synchronize{Dispatcher.dispatch(cgi, ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS, cgi.stdoutput)}
|
22
|
-
rescue IOError
|
23
|
-
@log.error("received IOError #$! when handling client. Your web server doesn't like me.")
|
24
|
-
rescue Object => rails_error
|
25
|
-
@log.error("calling Dispatcher.dispatch", rails_error)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|