scgi 0.7.0 → 0.8.0
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/{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
|