mongrel2 0.53.0 → 0.54.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d437852dd09b80cd9925ec41dbc8b29d9d2d0d758e30cd5acab9d378167fd1bd
4
- data.tar.gz: 1de4e99640b27b825d1540e28d99ec0d9338f1cf6907ed34217cb10c87f6163d
3
+ metadata.gz: '078af1a5d9ded05f97bdc0f0ffb9491480ee1102372e454ffbd3af91326f2206'
4
+ data.tar.gz: 8203090de25b79b5cbee3a8d57c64f4b3d9336e4bb5ab3739008d53c5a217e26
5
5
  SHA512:
6
- metadata.gz: 398bf47544d029215eb81829999ea3fd3438e03576cb1be8abbc9e5a842bb95044e29faf000d5e863e9b2f3ef5f69d1d15b33a647d1c13d9e1f3ad191f5f902a
7
- data.tar.gz: 39d7771ea0811fccb299d61cf960ee6d50e708012e099b7eec10dcf20290ecdb7b7bd01cb5db6eefc4bbe787d14a5eee7ad810963d13f43a5757d6b332f77d6f
6
+ metadata.gz: 50e7fff95804311a9f1aae03916b5b6d2a0910ce440696b006c942783b0be2d6cd1bd32ac5546e57ec5a2023529b69ef636b866e8f84c91cff2f69edbad8f046
7
+ data.tar.gz: 8d3c22401d5ea408ae3415bf5c8af8512d5bf58418c46fb8497d9aadba4aa33967ab06aca29b8f43151c8e39afe52731caf0ab92c9c828196f75a792d92273a6
Binary file
data.tar.gz.sig CHANGED
Binary file
data/ChangeLog CHANGED
@@ -1,9 +1,63 @@
1
+ 2019-09-04 Michael Granger <ged@FaerieMUD.org>
2
+
3
+ @ * lib/mongrel2/cli/_.rb:
4
+ | Remove the temporary command template
5
+ | [a45595593fe9] [tip]
6
+ |
7
+ o * .hgignore, Gemfile, Rakefile, gem.deps.rb, mongrel2.gemspec:
8
+ | Move deps to Rubygems style
9
+ | [3394aa0fb6d7]
10
+ |
11
+ 2019-08-30 Michael Granger <ged@FaerieMUD.org>
12
+
13
+ o * bin/m2sh.rb:
14
+ | Convert the `version` command
15
+ | [f0e8cc815f35]
16
+ |
17
+ o * bin/m2sh.rb, lib/mongrel2/cli/settings.rb:
18
+ | Add the `settings` command
19
+ | [3318e96c026c]
20
+ |
21
+ o * .gems, bin/m2sh.rb, example.rb, lib/mongrel2/cli.rb,
22
+ | lib/mongrel2/cli/_.rb, lib/mongrel2/cli/access.rb,
23
+ | lib/mongrel2/cli/bootstrap.rb, lib/mongrel2/cli/commit.rb,
24
+ | lib/mongrel2/cli/hosts.rb, lib/mongrel2/cli/init.rb,
25
+ | lib/mongrel2/cli/load.rb, lib/mongrel2/cli/log.rb,
26
+ | lib/mongrel2/cli/quickstart.rb, lib/mongrel2/cli/reload.rb,
27
+ | lib/mongrel2/cli/routes.rb, lib/mongrel2/cli/running.rb,
28
+ | lib/mongrel2/cli/servers.rb, lib/mongrel2/cli/start.rb,
29
+ | lib/mongrel2/cli/stop.rb, lib/mongrel2/config/directory.rb,
30
+ | lib/mongrel2/config/handler.rb, lib/mongrel2/config/proxy.rb,
31
+ | mongrel2.gemspec:
32
+ | Convert a bunch more commands to GLI
33
+ | [a3e36d56b290]
34
+ |
35
+ 2019-08-14 Michael Granger <ged@FaerieMUD.org>
36
+
37
+ o * certs/ged.pem:
38
+ | Update my gem-signing cert
39
+ | [3ace11b97f05]
40
+ |
41
+ o * lib/mongrel2/config.rb, lib/mongrel2/config/dsl.rb,
42
+ | lib/mongrel2/config/host.rb, lib/mongrel2/config/server.rb,
43
+ | spec/mongrel2/config/dsl_spec.rb:
44
+ | Fixed create vs. re-create in config DSL
45
+ | [62a155659470]
46
+ |
1
47
  2019-06-26 Michael Granger <ged@FaerieMUD.org>
2
48
 
3
- @ * History.rdoc, Rakefile, lib/mongrel2.rb:
49
+ o * .hgtags:
50
+ | Added tag v0.53.0 for changeset 9a0ef111c743
51
+ | [f2fa2ed85e26]
52
+ |
53
+ o * .hgsigs:
54
+ | Added signature for changeset cfedd3805c13
55
+ | [9a0ef111c743] [v0.53.0]
56
+ |
57
+ o * History.rdoc, Rakefile, lib/mongrel2.rb:
4
58
  | Bump the minor version, update history, bump minimum Ruby version to
5
59
  | 2.4.x
6
- | [cfedd3805c13] [tip]
60
+ | [cfedd3805c13]
7
61
  |
8
62
  o * Manifest.txt, lib/mongrel2/table.rb, lib/mongrel2/testing.rb,
9
63
  | spec/mongrel2/testing_spec.rb:
@@ -1,3 +1,10 @@
1
+ == v0.54.0 [2019-09-04] Michael Granger <ged@FaerieMUD.org>
2
+
3
+ Enhancements:
4
+
5
+ - Convert the CLI to use GLI instead of (deprecated) Trollop
6
+
7
+
1
8
  == v0.53.0 [2019-05-07] Michael Granger <ged@FaerieMUD.org>
2
9
 
3
10
  Enhancements:
@@ -11,7 +11,24 @@ bin/m2sh.rb
11
11
  data/mongrel2/config.rb.in
12
12
  data/mongrel2/config.sql
13
13
  data/mongrel2/mimetypes.sql
14
+ gem.deps.rb
14
15
  lib/mongrel2.rb
16
+ lib/mongrel2/cli.rb
17
+ lib/mongrel2/cli/access.rb
18
+ lib/mongrel2/cli/bootstrap.rb
19
+ lib/mongrel2/cli/commit.rb
20
+ lib/mongrel2/cli/hosts.rb
21
+ lib/mongrel2/cli/init.rb
22
+ lib/mongrel2/cli/load.rb
23
+ lib/mongrel2/cli/log.rb
24
+ lib/mongrel2/cli/quickstart.rb
25
+ lib/mongrel2/cli/reload.rb
26
+ lib/mongrel2/cli/routes.rb
27
+ lib/mongrel2/cli/running.rb
28
+ lib/mongrel2/cli/servers.rb
29
+ lib/mongrel2/cli/settings.rb
30
+ lib/mongrel2/cli/start.rb
31
+ lib/mongrel2/cli/stop.rb
15
32
  lib/mongrel2/config.rb
16
33
  lib/mongrel2/config/directory.rb
17
34
  lib/mongrel2/config/dsl.rb
data/Rakefile CHANGED
@@ -25,24 +25,27 @@ hoespec = Hoe.spec 'mongrel2' do
25
25
 
26
26
  self.developer 'Michael Granger', 'ged@FaerieMUD.org'
27
27
 
28
- self.dependency 'cztop', '~> 0.11'
29
- self.dependency 'cztop-reactor', '~> 0.6'
30
- self.dependency 'libxml-ruby', '~> 3.0'
31
- self.dependency 'loggability', '~> 0.12'
32
- self.dependency 'sequel', '~> 5.2'
33
- self.dependency 'sqlite3', '~> 1.3'
34
- self.dependency 'sysexits', '~> 1.1'
35
- self.dependency 'tnetstring', '~> 0.3'
36
- self.dependency 'trollop', '~> 2.0'
37
- self.dependency 'yajl-ruby', '~> 1.0'
38
-
39
- self.dependency 'amalgalite', '~> 1.5', :developer
40
- self.dependency 'configurability', '~> 3.1', :developer
41
- self.dependency 'simplecov', '~> 0.12', :developer
42
- self.dependency 'hoe-deveiate', '~> 0.8', :developer
43
- self.dependency 'rdoc-generator-fivefish', '~> 0', :development
44
-
45
- self.require_ruby_version( '>=2.4.0' )
28
+ self.dependency 'cztop', '~> 0.11'
29
+ self.dependency 'cztop-reactor', '~> 0.6'
30
+ self.dependency 'gli', '~> 2.19'
31
+ self.dependency 'libxml-ruby', '~> 3.1'
32
+ self.dependency 'loggability', '~> 0.14'
33
+ self.dependency 'pastel', '~> 0.7'
34
+ self.dependency 'sequel', '~> 5.2'
35
+ self.dependency 'sqlite3', '~> 1.3'
36
+ self.dependency 'sysexits', '~> 1.1'
37
+ self.dependency 'tnetstring', '~> 0.3'
38
+ self.dependency 'tty-prompt', '~> 0.19'
39
+ self.dependency 'tty-table', '~> 0.11'
40
+ self.dependency 'yajl-ruby', '~> 1.4'
41
+
42
+ self.dependency 'amalgalite', '~> 1.5', :developer
43
+ self.dependency 'configurability', '~> 3.4', :developer
44
+ self.dependency 'hoe-deveiate', '~> 0.10', :developer
45
+ self.dependency 'simplecov', '~> 0.12', :developer
46
+ self.dependency 'rdoc-generator-fivefish', '~> 0', :developer
47
+
48
+ self.require_ruby_version( '>=2.5.0' )
46
49
  self.hg_sign_tags = true if self.respond_to?( :hg_sign_tags= )
47
50
  self.check_history_on_release = true if self.respond_to?( :check_history_on_release= )
48
51
  self.rdoc_locations << "deveiate:/usr/local/www/public/code/#{remote_rdoc_dir}"
@@ -1,744 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'uri'
4
- require 'pathname'
5
- require 'fileutils'
6
- require 'tnetstring'
7
3
  require 'loggability'
8
- require 'shellwords'
4
+ Loggability.level = :fatal
9
5
 
10
- require 'trollop'
11
- require 'highline'
6
+ require 'mongrel2/cli'
7
+ exit Mongrel2::CLI.run( ARGV )
12
8
 
13
- # Have to do it this way to avoid the vendored 'sysexits' under OSX.
14
- gem 'sysexits'
15
- require 'sysexits'
16
-
17
- require 'mongrel2'
18
- require 'mongrel2/config'
19
-
20
-
21
- # A tool for interacting with a Mongrel2 config database and server. This isn't
22
- # quite a replacement for the real m2sh yet; here's what I have working so far:
23
- #
24
- # [√] load Load a config.
25
- # [√] config Alias for load.
26
- # [-] shell Starts an interactive shell.
27
- # [√] access Prints the access log.
28
- # [√] servers Lists the servers in a config database.
29
- # [√] hosts Lists the hosts in a server.
30
- # [√] routes Lists the routes in a host.
31
- # [√] commit Adds a message to the log.
32
- # [√] log Prints the commit log.
33
- # [√] start Starts a server.
34
- # [√] stop Stops a server.
35
- # [√] reload Reloads a server.
36
- # [√] running Tells you what's running.
37
- # [-] control Connects to the control port.
38
- # [√] version Prints the Mongrel2 and m2sh version.
39
- # [√] help Get help, lists commands.
40
- # [-] uuid Prints out a randomly generated UUID.
41
- #
42
- # I just use 'uuidgen' to generate uuids (which is all m2sh does, as
43
- # well), so I don't plan to implement that. The 'control' command is more-easily
44
- # accessed via pry+Mongrel2::Control, so I'm not going to implement that, either.
45
- # Everything else should be analagous to (or better than) the m2sh that comes with
46
- # mongrel2. I implemented the 'shell' mode, but I found I never used it, and it
47
- # introduced a dependency on the Termios library, so I removed it.
48
- #
49
- class Mongrel2::M2SHCommand
50
- extend ::Sysexits,
51
- Loggability
52
- include Sysexits,
53
- Mongrel2::Constants
54
-
55
- # Loggability API -- set up logging under the 'strelka' log host
56
- log_to :mongrel2
57
-
58
-
59
- # Make a HighLine color scheme
60
- COLOR_SCHEME = HighLine::ColorScheme.new do |scheme|
61
- scheme[:header] = [ :bold, :yellow ]
62
- scheme[:subheader] = [ :bold, :white ]
63
- scheme[:key] = [ :white ]
64
- scheme[:value] = [ :bold, :white ]
65
- scheme[:error] = [ :red ]
66
- scheme[:warning] = [ :yellow ]
67
- scheme[:message] = [ :reset ]
68
- end
69
-
70
-
71
- # Number of items to store in history by default
72
- DEFAULT_HISTORY_SIZE = 100
73
-
74
-
75
- # Class instance variables
76
- @command_help = Hash.new {|h,k| h[k] = { :desc => nil, :usage => ''} }
77
- @prompt = @option_parser = nil
78
-
79
-
80
- ### Add a help string for the given +command+.
81
- def self::help( command, helpstring=nil )
82
- if helpstring
83
- @command_help[ command.to_sym ][:desc] = helpstring
84
- end
85
-
86
- return @command_help[ command.to_sym ][:desc]
87
- end
88
-
89
-
90
- ### Add/fetch the +usagestring+ for +command+.
91
- def self::usage( command, usagestring=nil )
92
- if usagestring
93
- prefix = usagestring[ /\A(\s+)/, 1 ]
94
- usagestring.gsub!( /^#{prefix}/m, '' ) if prefix
95
-
96
- @command_help[ command.to_sym ][:usage] = usagestring
97
- end
98
-
99
- return @command_help[ command.to_sym ][:usage]
100
- end
101
-
102
-
103
- ### Return the global Highline prompt object, creating it if necessary.
104
- def self::prompt
105
- unless @prompt
106
- @prompt = HighLine.new
107
- # @prompt.wrap_at = @prompt.output_cols - 3
108
- end
109
-
110
- return @prompt
111
- end
112
-
113
-
114
- ### Run the utility with the given +args+.
115
- def self::run( args )
116
- HighLine.color_scheme = COLOR_SCHEME
117
-
118
- oparser = self.make_option_parser
119
- opts = Trollop.with_standard_exception_handling( oparser ) do
120
- oparser.parse( args )
121
- end
122
-
123
- command = oparser.leftovers.shift
124
- self.new( opts ).run( command, *oparser.leftovers )
125
- exit :ok
126
-
127
- rescue => err
128
- self.log.fatal "Oops: %s: %s" % [ err.class.name, err.message ]
129
- self.log.debug { ' ' + err.backtrace.join("\n ") }
130
-
131
- exit :software_error
132
- end
133
-
134
-
135
- ### Return a String that describes the available commands, e.g., for the 'help'
136
- ### command.
137
- def self::make_command_table
138
- commands = self.available_commands
139
-
140
- # Build the command table
141
- col1len = commands.map( &:length ).max
142
- return commands.collect do |cmd|
143
- helptext = self.help( cmd.to_sym ) or next # no help == invisible command
144
- "%s %s" % [
145
- self.prompt.color(cmd.rjust(col1len), :key),
146
- self.prompt.color(helptext, :value)
147
- ]
148
- end.compact
149
- end
150
-
151
-
152
- ### Return an Array of the available commands.
153
- def self::available_commands
154
- return self.public_instance_methods( false ).
155
- map( &:to_s ).
156
- grep( /_command$/ ).
157
- map {|methodname| methodname.sub(/_command$/, '') }.
158
- sort
159
- end
160
-
161
-
162
- ### Create and configure a command-line option parser for the command.
163
- ### Returns a Trollop::Parser.
164
- def self::make_option_parser
165
- unless @option_parser
166
- progname = File.basename( $0 )
167
- default_configdb = Mongrel2::DEFAULT_CONFIG_URI
168
-
169
- # Make a list of the log level names and the available commands
170
- loglevels = Loggability::LOG_LEVELS.
171
- sort_by {|name,lvl| lvl }.
172
- collect {|name,lvl| name.to_s }.
173
- join( ', ' )
174
- command_table = self.make_command_table
175
-
176
- @option_parser = Trollop::Parser.new do
177
- banner "Mongrel2 (Ruby) Shell has these commands available:"
178
-
179
- text ''
180
- command_table.each {|line| text(line) }
181
- text ''
182
-
183
- text 'Global Options'
184
- opt :config, "Specify the config database to use.",
185
- :default => DEFAULT_CONFIG_URI
186
- opt :sudo, "Use 'sudo' to run the mongrel2 server."
187
- opt :port, "Reset the server port to <i> before starting it.",
188
- :type => :integer
189
- opt :why, "Specify the reason for an action for the event log.",
190
- :type => :string
191
- text ''
192
-
193
- text 'Other Options:'
194
- opt :debug, "Turn debugging on. Also sets the --loglevel to 'debug'."
195
- opt :loglevel, "Set the logging level. Must be one of: #{loglevels}",
196
- :default => Mongrel2.logger.level.to_s
197
- end
198
- end
199
-
200
- return @option_parser
201
- end
202
-
203
-
204
- #################################################################
205
- ### I N S T A N C E M E T H O D S
206
- #################################################################
207
-
208
- ### Create a new instance of the command and set it up with the given
209
- ### +options+.
210
- def initialize( options )
211
- Loggability.format_as( :color ) if $stderr.tty?
212
- @options = options
213
-
214
- if @options.debug
215
- $DEBUG = true
216
- $VERBOSE = true
217
- Loggability.level = Logger::DEBUG
218
- elsif @options.loglevel
219
- Loggability.level = @options.loglevel
220
- end
221
-
222
- Mongrel2::Config.configure( :configdb => @options.config )
223
- end
224
-
225
-
226
- ######
227
- public
228
- ######
229
-
230
- # The Trollop options hash the command will read its configuration from
231
- attr_reader :options
232
-
233
-
234
- # Delegate the instance #prompt method to the class method instead
235
- define_method( :prompt, &self.method(:prompt) )
236
-
237
-
238
- ### Run the command with the specified +command+ and +args+.
239
- def run( command, *args )
240
- command ||= 'help'
241
- cmd_method = nil
242
-
243
- begin
244
- cmd_method = self.method( "#{command}_command" )
245
- rescue NoMethodError => err
246
- error "No such command"
247
- exit :usage
248
- end
249
-
250
- cmd_method.call( *args )
251
- end
252
-
253
-
254
- #
255
- # Commands
256
- #
257
-
258
- ### The 'help' command
259
- def help_command( *args )
260
-
261
- # Subcommand help
262
- if !args.empty?
263
- command = args.shift
264
-
265
- if self.class.available_commands.include?( command )
266
- header( self.class.help(command) )
267
- desc = "\n" + 'Usage: ' + command + ' ' + self.class.usage(command) + "\n"
268
- message( desc )
269
- else
270
- error "No such command %p" % [ command ]
271
- end
272
-
273
- # Help by itself show the table of available commands
274
- else
275
- command_table = self.class.make_command_table
276
- header "Available Commands"
277
- message( *command_table )
278
- end
279
-
280
- end
281
- help :help, "Show help for a single COMMAND if given, or list available commands if not"
282
- usage :help, "[COMMAND]"
283
-
284
-
285
- ### The 'load' command
286
- def load_command( *args )
287
- configfile = args.shift or
288
- raise "No configfile specified."
289
-
290
- runspace = Module.new do
291
- extend Mongrel2::Config::DSL, FileUtils::Verbose
292
- end
293
-
294
- header "Loading config from #{configfile}"
295
- source = File.read( configfile )
296
-
297
- runspace.module_eval( source, configfile, 1 )
298
- Mongrel2::Config.log_action( "Loaded config from #{configfile}", self.options.why )
299
- end
300
- help :load, "Overwrite the config database with the values from the speciifed CONFIGFILE."
301
- usage :load, <<-END_USAGE
302
- CONFIGFILE
303
- Note: the CONFIGFILE should contain a configuration described using the
304
- Ruby config DSL, not a Python-ish normal one. m2sh already works perfectly
305
- fine for loading those.
306
- END_USAGE
307
-
308
-
309
- ### The 'config' command
310
- alias_method :config_command, :load_command
311
- help :config, "Alias for 'load'."
312
-
313
-
314
- ### The 'init' command
315
- def init_command( * )
316
- if Mongrel2::Config.database_initialized?
317
- abort "Okay, aborting." unless
318
- self.prompt.agree( "Are you sure you want to destroy the current config? " )
319
- end
320
-
321
- header "Initializing #{self.options.config}"
322
- Mongrel2::Config.init_database!
323
- end
324
- help :init, "Initialize a new empty config database."
325
-
326
-
327
- ### The 'access' command
328
- def access_command( logfile='logs/access.log', * )
329
- # 1$ 2$ 3$ 4$ 5$ 6$ 7$ 8$ 9$
330
- # ["localhost", "127.0.0.1", 53420, 1315533812, "GET", "/favicon.ico", "HTTP/1.1", 404, 0]
331
- # -> [1315533812] 127.0.0.1:53420 localhost "GET /favicon.ico HTTP/1.1" 404 0
332
- IO.foreach( logfile ) do |line|
333
- row, _ = TNetstring.parse( line )
334
- message %{[%4$d] %2$s:%3$d %1$s "%5$s %6$s %7$s" %8$03d %9$d} % row
335
- end
336
- end
337
- help :access, "Dump the access log."
338
- usage :access, "[logfile]\nThe logfile defaults to 'logs/access.log'."
339
-
340
-
341
- ### The 'servers' command
342
- def servers_command( * )
343
- header 'SERVERS:'
344
- Mongrel2::Config.servers.each do |server|
345
- message "%s [%s]: %s" % [
346
- self.prompt.color( server.name, :key ),
347
- server.default_host,
348
- server.uuid,
349
- ]
350
- end
351
- end
352
- help :servers, "Lists the servers in a config database."
353
-
354
-
355
- ### The 'hosts' command
356
- def hosts_command( *args )
357
- servername = args.shift
358
-
359
- # Start with all servers, then narrow it down if they specified a server name.
360
- servers = Mongrel2::Config::Server.dataset
361
- servers = servers.filter( :name => servername ) if servername
362
-
363
- # Output a section for each server
364
- servers.each do |server|
365
- header "HOSTS for server #{server.name}:"
366
- server.hosts.each do |host|
367
- line = "%d: %s" % [ host.id, host.name ]
368
- line << " /%s/" % [ host.matching ] if host.matching != host.name
369
-
370
- message( line )
371
- end
372
-
373
- $stdout.puts
374
- end
375
- end
376
- help :hosts, "Lists the hosts in a server, or in all servers if none is specified."
377
- usage :hosts, "[server]"
378
-
379
-
380
- ### The 'routes' command
381
- def routes_command( *args )
382
- servername = args.shift
383
- hostname = args.shift
384
-
385
- # Start with all hosts, then narrow it down if a server and/or host was given.
386
- hosts = Mongrel2::Config::Host.dataset
387
- if servername
388
- server = Mongrel2::Config::Server[ servername ] or
389
- raise "No such server '#{servername}'"
390
- hosts = server.hosts_dataset
391
- end
392
- hosts = hosts.filter( :name => hostname ) if hostname
393
-
394
- # Output a section for each host
395
- hosts.each do |host|
396
- header "ROUTES for host #{host.server.name}/#{host.name}:"
397
-
398
- host.routes.each do |route|
399
- message( route.path )
400
- end
401
- end
402
-
403
- end
404
- help :routes, "Show the routes under a host."
405
- usage :routes, "[server [host]]"
406
-
407
-
408
- ### The 'commit' command
409
- def commit_command( *args )
410
- what, where, why, how = *args
411
- what ||= ''
412
-
413
- log = Mongrel2::Config::Log.log_action( what, where, why, how )
414
-
415
- header "Okay, logged."
416
- message( log.to_s )
417
- end
418
- help :commit, "Add a message to the commit log."
419
- usage :commit, "[WHAT [WHERE [WHY [HOW]]]]"
420
-
421
-
422
- ### The 'log' command
423
- def log_command( *args )
424
- header "Log Messages"
425
- Mongrel2::Config::Log.order_by( :happened_at ).each do |log|
426
- message( log.to_s )
427
- end
428
- end
429
- help :log, "Prints the commit log."
430
-
431
-
432
- ### The 'start' command
433
- def start_command( *args )
434
- server = find_server( args.shift )
435
- mongrel2 = find_mongrel2()
436
-
437
- if options.port
438
- message "Resetting %s server's port to %d" % [ server.name, options.port ]
439
- server.port = options.port
440
- server.save
441
- end
442
-
443
- cmd = [ mongrel2.to_s, Mongrel2::Config.dbname.to_s, server.uuid ]
444
- cmd.unshift( 'sudo' ) if self.options.sudo
445
-
446
- url = "http%s://%s:%d" % [
447
- server.use_ssl? ? 's' : '',
448
- server.bind_addr,
449
- server.port,
450
- ]
451
-
452
- # Change into the server's chroot directory so paths line up whether or not
453
- # it's started as root
454
-
455
- message '*' * 70
456
- header "Starting mongrel2 at: #{url}"
457
- message '*' * 70
458
-
459
- if server.chroot && server.chroot != '' && server.chroot != '.'
460
- Dir.chdir( server.chroot )
461
- message " changed PWD to: #{Dir.pwd}"
462
- end
463
-
464
- Mongrel2::Config.log_action( "Starting server: #{server}", self.options.why )
465
- self.log.debug " command is: #{Shellwords.shelljoin(cmd)}"
466
- exec( *cmd )
467
- end
468
- help :start, "Starts a server."
469
- usage :start, <<-END_USAGE
470
- [SERVER]
471
- If not specified, SERVER is assumed to be the only server entry in the
472
- current config. If there are more than one, you must specify a SERVER.
473
-
474
- The SERVER can be a uuid, hostname, or server name, and are searched for
475
- in that order.
476
- END_USAGE
477
-
478
-
479
- ### The 'reload' command
480
- def reload_command( *args )
481
- server = find_server( args.shift )
482
- control = server.control_socket
483
-
484
- header "Reloading '%s'" % [ server.name ]
485
- control.reload
486
- control.close
487
- message "done."
488
-
489
- Mongrel2::Config.log_action( "Restarted server #{server}", self.options.why )
490
- end
491
- help :reload, "Reload the specified server's configuration"
492
- usage :reload, "[server]"
493
-
494
-
495
- ### The 'stop' command
496
- def stop_command( *args )
497
- server = find_server( args.shift )
498
- control = server.control_socket
499
-
500
- header "Stopping '%s' gracefully." % [ server.name ]
501
- control.stop
502
- control.close
503
- message "done."
504
-
505
- Mongrel2::Config.log_action( "Stopped server #{server}", self.options.why )
506
- end
507
- help :stop, "Stop the specified server gracefully"
508
- usage :stop, "[server]"
509
-
510
-
511
- ### The 'running' command
512
- def running_command( *args )
513
- server = find_server( args.shift )
514
- pidfile = server.pid_file_path
515
-
516
- header "Checking the status of the '%s' server." % [ server.name ]
517
- unless pidfile.exist?
518
- message "Not running: PID file (%s) doesn't exist." % [ pidfile ]
519
- exit :noinput
520
- end
521
-
522
- pid = Integer( pidfile.read )
523
- begin
524
- Process.kill( 0, pid )
525
- rescue Errno::ESRCH
526
- message " mongrel2 at PID %d is NOT running" % [ pid ]
527
- exit :unavailable
528
- rescue => err
529
- error " %p while signalling PID %d: %s" % [ err.class, pid, err.message ]
530
- end
531
-
532
- message " mongrel2 at PID %d is running." % [ pid ]
533
- end
534
- help :running, "Show the status of a server."
535
- usage :running, "[server]"
536
-
537
-
538
- ### The 'bootstrap' command.
539
- def bootstrap_command( *args )
540
- scriptname = args.shift || DEFAULT_CONFIG_SCRIPT
541
- template = Mongrel2::DATA_DIR + 'config.rb.in'
542
-
543
- # Read the config DSL template
544
- data = template.read
545
- data.gsub!( /%% PWD %%/, Dir.pwd )
546
-
547
- # Write it out
548
- header "Writing a config-generation script to %s" % [ scriptname ]
549
- File.open( scriptname, File::WRONLY|File::EXCL|File::CREAT, 0755, encoding: 'utf-8' ) do |fh|
550
- fh.print( data )
551
- end
552
- message "Done."
553
- end
554
- help :bootstrap, "Generate a basic config-generation script."
555
- usage :boostrap, "[scriptname]"
556
-
557
-
558
- ### The 'quickstart' command.
559
- def quickstart_command( *args )
560
- idx_template = Mongrel2::DATA_DIR + 'index.html.in'
561
- configfile = 'config.rb'
562
-
563
- header "Quickstart!"
564
- self.bootstrap_command( configfile )
565
- edit( configfile )
566
- self.load_command( configfile )
567
-
568
- # Now load the new config DB and fetch the configured server
569
- host = Mongrel2::Config.servers.first.hosts.first
570
- hello_route = host.routes_dataset.filter( target_type: 'handler' ).first
571
-
572
- # Read the index page template
573
- data = idx_template.read
574
- data.gsub!( /%% VERSION %%/, Mongrel2.version_string(true) )
575
- data.gsub!( /%% HELLOWORLD_SEND_SPEC %%/, hello_route.target.send_spec )
576
- data.gsub!( /%% HELLOWORLD_RECV_SPEC %%/, hello_route.target.recv_spec )
577
- data.gsub!( /%% HELLOWORLD_URI %%/, hello_route.path[ /([^\(]*)/ ] )
578
-
579
- # Write it out to the public directory
580
- header "Writing an index file to public/index.html"
581
- Dir.mkdir( 'public' ) unless File.directory?( 'public' )
582
- File.open( 'public/index.html', File::WRONLY|File::EXCL|File::CREAT, 0755,
583
- encoding: 'utf-8' ) do |fh|
584
- fh.print( data )
585
- end
586
- message "Done."
587
-
588
- self.start_command()
589
- end
590
- help :quickstart, "Set up a basic mongrel2 server and run it."
591
- usage :quickstart
592
-
593
-
594
- ### The 'settings' command
595
- def settings_command( *args )
596
- header "Advanced Server Settings"
597
- Mongrel2::Config.settings.each do |key,val|
598
- message( %{<%= color "#{key}:", :subheader %> #{val}} )
599
- end
600
- end
601
- help :settings, "Show the 'advanced' server settings."
602
- usage :settings
603
-
604
-
605
- ### The 'version' command
606
- def version_command( *args )
607
- message( "<%= color 'Version:', :header %> " + Mongrel2.version_string(true) )
608
- end
609
- help :version, "Prints the Ruby-Mongrel2 version."
610
-
611
-
612
- #
613
- # Utility methods
614
- #
615
-
616
- #######
617
- private
618
- #######
619
-
620
- ### Output normal output
621
- def message( *parts )
622
- self.prompt.say( parts.map(&:to_s).join($/) )
623
- end
624
-
625
-
626
- ### Output the given +text+ highlighted as a header.
627
- def header( text )
628
- message( self.prompt.color(text, :header) )
629
- end
630
-
631
-
632
- ### Output the given +text+ highlighted as an error.
633
- def error( text )
634
- message( self.prompt.color(text, :error) )
635
- end
636
-
637
-
638
- ### Read command line history from HISTORY_FILE
639
- def read_history
640
- histfile = HISTORY_FILE.expand_path
641
-
642
- if histfile.exist?
643
- lines = histfile.readlines.collect {|line| line.chomp }
644
- self.log.debug "Read %d saved history commands from %s." % [ lines.length, histfile ]
645
- Readline::HISTORY.push( *lines )
646
- else
647
- self.log.debug "History file '%s' was empty or non-existant." % [ histfile ]
648
- end
649
- end
650
-
651
-
652
- ### Save command line history to HISTORY_FILE
653
- def save_history
654
- histfile = HISTORY_FILE.expand_path
655
-
656
- lines = Readline::HISTORY.to_a.reverse.uniq.reverse
657
- lines = lines[ -DEFAULT_HISTORY_SIZE, DEFAULT_HISTORY_SIZE ] if
658
- lines.length > DEFAULT_HISTORY_SIZE
659
-
660
- self.log.debug "Saving %d history lines to %s." % [ lines.length, histfile ]
661
-
662
- histfile.open( File::WRONLY|File::CREAT|File::TRUNC ) do |ofh|
663
- ofh.puts( *lines )
664
- end
665
- end
666
-
667
-
668
- ### Search the current mongrel2 config for a server matching +serverspec+ and
669
- ### return it as a Mongrel2::Config::Server object.
670
- def find_server( serverspec=nil )
671
- server = nil
672
- servers = Mongrel2::Config.servers
673
-
674
- raise "No servers are configured." if servers.empty?
675
-
676
- # If there's only one configured server, just make sure if a serverspec was given
677
- # that it would have matched.
678
- if servers.length == 1
679
- server = servers.first if !serverspec ||
680
- servers.first.values.values_at( :uuid, :default_host, :name ).include?( serverspec )
681
-
682
- # Otherwise, require an argument and search for the desired server if there is one
683
- else
684
- raise "You must specify a server uuid/hostname/name when more " +
685
- "than one server is configured." if servers.length > 1 && !serverspec
686
-
687
- server = servers.find {|s| s.uuid == serverspec } ||
688
- servers.find {|s| s.default_host == serverspec } ||
689
- servers.find {|s| s.name == serverspec }
690
- end
691
-
692
- raise "No servers match '#{serverspec}'" unless server
693
-
694
- return server
695
- end
696
-
697
-
698
- ### Invoke the user's editor on the given +filename+ and return the exit code
699
- ### from doing so.
700
- def edit( filename )
701
- editor = ENV['EDITOR'] || ENV['VISUAL'] || DEFAULT_EDITOR
702
- system editor, filename.to_s
703
- unless $?.success? || editor =~ /vim/i
704
- raise "Editor exited with an error status (%d)" % [ $?.exitstatus ]
705
- end
706
- end
707
-
708
-
709
- ### Search the PATH for a mongrel2 binary, returning the absolute Pathname to it if found, and
710
- ### outputting a warning and describing how to set ENV['MONGREL2'] if not.
711
- def find_mongrel2
712
- if ENV['MONGREL2']
713
- m2 = Pathname( ENV['MONGREL2'] )
714
- error = nil
715
- if !m2.file?
716
- error = "but it isn't a plain file."
717
- elsif !m2.executable?
718
- error = "but it isn't executable."
719
- end
720
-
721
- raise "MONGREL2 was set to #{m2}, #{error}" if error
722
-
723
- return m2
724
- else
725
- m2 = ENV['PATH'].split( File::PATH_SEPARATOR ).
726
- map {|dir| Pathname(dir) + 'mongrel2' }.
727
- find {|path| path.executable? }
728
-
729
- return m2 if m2
730
-
731
- raise "The 'mongrel2' binary doesn't seem to be in your PATH. Either " +
732
- "add the appropriate directory to your PATH or set the MONGREL2 " +
733
- "environment variable to the full path."
734
- end
735
-
736
- end
737
-
738
-
739
-
740
- end # class Mongrel2::M2SHCommand
741
-
742
-
743
- Mongrel2::M2SHCommand.run( ARGV.dup )
744
9