passenger 4.0.2 → 4.0.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of passenger might be problematic. Click here for more details.
- data.tar.gz.asc +7 -7
- data/NEWS +27 -0
- data/bin/passenger-config +6 -3
- data/bin/passenger-install-apache2-module +2 -2
- data/bin/passenger-install-nginx-module +16 -2
- data/build/agents.rb +4 -0
- data/build/apache2.rb +1 -1
- data/build/cplusplus_support.rb +1 -1
- data/build/cxx_tests.rb +3 -0
- data/build/packaging.rb +51 -8
- data/build/ruby_extension.rb +1 -1
- data/doc/Packaging.txt.md +20 -7
- data/doc/Users guide Apache.html +1 -1
- data/doc/Users guide Apache.txt +1 -1
- data/doc/Users guide Nginx.html +5 -4
- data/doc/Users guide Nginx.txt +1 -1
- data/doc/users_guide_snippets/installation.txt +5 -3
- data/ext/apache2/Configuration.cpp +12 -0
- data/ext/apache2/Configuration.hpp +7 -4
- data/ext/apache2/Hooks.cpp +29 -19
- data/ext/common/AgentsStarter.cpp +85 -57
- data/ext/common/AgentsStarter.h +570 -42
- data/ext/common/ApplicationPool2/DirectSpawner.h +5 -2
- data/ext/common/ApplicationPool2/Implementation.cpp +7 -1
- data/ext/common/ApplicationPool2/Pool.h +6 -3
- data/ext/common/ApplicationPool2/Process.h +12 -3
- data/ext/common/ApplicationPool2/SmartSpawner.h +2 -1
- data/ext/common/Constants.h +4 -1
- data/ext/common/EventedBufferedInput.h +139 -16
- data/ext/common/MultiLibeio.cpp +4 -2
- data/ext/common/SafeLibev.h +15 -62
- data/ext/common/ServerInstanceDir.h +10 -26
- data/ext/common/Utils.cpp +1 -3
- data/ext/common/Utils.h +1 -1
- data/ext/common/Utils/StrIntUtils.cpp +9 -0
- data/ext/common/Utils/StrIntUtils.h +5 -0
- data/ext/common/Utils/VariantMap.h +63 -14
- data/ext/common/agents/Base.cpp +50 -15
- data/ext/common/agents/HelperAgent/AgentOptions.h +20 -12
- data/ext/common/agents/HelperAgent/FileBackedPipe.h +1 -1
- data/ext/common/agents/HelperAgent/Main.cpp +5 -4
- data/ext/common/agents/HelperAgent/RequestHandler.h +1 -1
- data/ext/common/agents/LoggingAgent/Main.cpp +0 -1
- data/ext/common/agents/LoggingAgent/RemoteSender.h +2 -2
- data/ext/common/agents/SpawnPreparer.cpp +23 -5
- data/ext/common/agents/Watchdog/AgentWatcher.cpp +508 -0
- data/ext/common/agents/Watchdog/HelperAgentWatcher.cpp +93 -0
- data/ext/common/agents/Watchdog/LoggingAgentWatcher.cpp +68 -0
- data/ext/common/agents/Watchdog/Main.cpp +180 -802
- data/ext/common/agents/Watchdog/ServerInstanceDirToucher.cpp +111 -0
- data/ext/nginx/Configuration.c +107 -92
- data/ext/nginx/Configuration.h +1 -0
- data/ext/nginx/ContentHandler.c +6 -6
- data/ext/nginx/ContentHandler.h +1 -1
- data/ext/nginx/config +8 -2
- data/ext/nginx/ngx_http_passenger_module.c +54 -60
- data/ext/nginx/ngx_http_passenger_module.h +6 -6
- data/lib/phusion_passenger.rb +17 -10
- data/lib/phusion_passenger/admin_tools/server_instance.rb +2 -2
- data/lib/phusion_passenger/common_library.rb +0 -1
- data/lib/phusion_passenger/platform_info.rb +10 -1
- data/lib/phusion_passenger/platform_info/depcheck.rb +4 -4
- data/lib/phusion_passenger/platform_info/depcheck_specs/compiler_toolchain.rb +2 -2
- data/lib/phusion_passenger/platform_info/ruby.rb +7 -0
- data/lib/phusion_passenger/request_handler.rb +119 -42
- data/lib/phusion_passenger/request_handler/thread_handler.rb +25 -22
- data/lib/phusion_passenger/standalone/command.rb +2 -0
- data/lib/phusion_passenger/standalone/runtime_installer.rb +4 -3
- data/lib/phusion_passenger/standalone/start_command.rb +49 -37
- data/resources/templates/nginx/pcre_checksum_could_not_be_verified.txt.erb +11 -0
- data/test/cxx/CxxTestMain.cpp +2 -0
- data/test/cxx/EventedBufferedInputTest.cpp +758 -0
- data/test/cxx/ServerInstanceDirTest.cpp +16 -31
- data/test/cxx/TestSupport.cpp +2 -1
- data/test/cxx/VariantMapTest.cpp +23 -11
- metadata +8 -4
- metadata.gz.asc +7 -7
- data/ext/common/AgentsStarter.hpp +0 -655
- data/lib/phusion_passenger/utils/robust_interruption.rb +0 -173
@@ -26,7 +26,6 @@ require 'phusion_passenger/debug_logging'
|
|
26
26
|
require 'phusion_passenger/message_channel'
|
27
27
|
require 'phusion_passenger/utils'
|
28
28
|
require 'phusion_passenger/utils/unseekable_socket'
|
29
|
-
require 'phusion_passenger/utils/robust_interruption'
|
30
29
|
|
31
30
|
module PhusionPassenger
|
32
31
|
class RequestHandler
|
@@ -36,7 +35,9 @@ class RequestHandler
|
|
36
35
|
class ThreadHandler
|
37
36
|
include DebugLogging
|
38
37
|
include Utils
|
39
|
-
|
38
|
+
|
39
|
+
class Interrupted < StandardError
|
40
|
+
end
|
40
41
|
|
41
42
|
REQUEST_METHOD = 'REQUEST_METHOD'.freeze
|
42
43
|
PING = 'PING'.freeze
|
@@ -53,9 +54,10 @@ class ThreadHandler
|
|
53
54
|
GC_SUPPORTS_TIME = GC.respond_to?(:time)
|
54
55
|
GC_SUPPORTS_CLEAR_STATS = GC.respond_to?(:clear_stats)
|
55
56
|
|
57
|
+
attr_reader :thread
|
56
58
|
attr_reader :stats_mutex
|
57
|
-
attr_reader :
|
58
|
-
attr_reader :
|
59
|
+
attr_reader :interruptable
|
60
|
+
attr_reader :iteration
|
59
61
|
|
60
62
|
def initialize(request_handler, options = {})
|
61
63
|
@request_handler = request_handler
|
@@ -69,9 +71,9 @@ class ThreadHandler
|
|
69
71
|
:connect_password
|
70
72
|
)
|
71
73
|
|
72
|
-
@stats_mutex
|
73
|
-
@
|
74
|
-
@
|
74
|
+
@stats_mutex = Mutex.new
|
75
|
+
@interruptable = false
|
76
|
+
@iteration = 0
|
75
77
|
|
76
78
|
if @protocol == :session
|
77
79
|
metaclass = class << self; self; end
|
@@ -89,8 +91,8 @@ class ThreadHandler
|
|
89
91
|
end
|
90
92
|
|
91
93
|
def install
|
92
|
-
Thread.current
|
93
|
-
|
94
|
+
@thread = Thread.current
|
95
|
+
Thread.current[:passenger_thread_handler] = self
|
94
96
|
PhusionPassenger.call_event(:starting_request_handler_thread)
|
95
97
|
end
|
96
98
|
|
@@ -102,26 +104,29 @@ class ThreadHandler
|
|
102
104
|
|
103
105
|
begin
|
104
106
|
finish_callback.call
|
105
|
-
while
|
107
|
+
while true
|
106
108
|
hijacked = accept_and_process_next_request(socket_wrapper, channel, buffer)
|
107
109
|
socket_wrapper = Utils::UnseekableSocket.new if hijacked
|
108
110
|
end
|
109
|
-
rescue
|
111
|
+
rescue Interrupted
|
110
112
|
# Do nothing.
|
111
113
|
end
|
112
114
|
debug("Thread handler main loop exited normally")
|
113
|
-
|
114
|
-
|
115
|
-
def idle?
|
116
|
-
@stats_mutex.synchronize { return !@processing }
|
115
|
+
ensure
|
116
|
+
@stats_mutex.synchronize { @interruptable = true }
|
117
117
|
end
|
118
118
|
|
119
119
|
private
|
120
120
|
# Returns true if the socket has been hijacked, false otherwise.
|
121
121
|
def accept_and_process_next_request(socket_wrapper, channel, buffer)
|
122
|
-
@stats_mutex.synchronize
|
123
|
-
|
124
|
-
|
122
|
+
@stats_mutex.synchronize do
|
123
|
+
@interruptable = true
|
124
|
+
end
|
125
|
+
connection = socket_wrapper.wrap(@server_socket.accept)
|
126
|
+
@stats_mutex.synchronize do
|
127
|
+
@interruptable = false
|
128
|
+
@iteration += 1
|
129
|
+
end
|
125
130
|
trace(3, "Accepted new request on socket #{@socket_name}")
|
126
131
|
channel.io = connection
|
127
132
|
if headers = parse_request(connection, channel, buffer)
|
@@ -149,6 +154,8 @@ private
|
|
149
154
|
else
|
150
155
|
trace(2, "No headers parsed; disconnecting client.")
|
151
156
|
end
|
157
|
+
rescue Interrupted
|
158
|
+
raise
|
152
159
|
rescue => e
|
153
160
|
if socket_wrapper && socket_wrapper.source_of_exception?(e)
|
154
161
|
# EPIPE is harmless, it just means that the client closed the connection.
|
@@ -177,10 +184,6 @@ private
|
|
177
184
|
rescue SystemCallError
|
178
185
|
end
|
179
186
|
end
|
180
|
-
@stats_mutex.synchronize do
|
181
|
-
@processed_requests += 1
|
182
|
-
@processing = false
|
183
|
-
end
|
184
187
|
end
|
185
188
|
|
186
189
|
def parse_session_request(connection, channel, buffer)
|
@@ -190,8 +190,10 @@ private
|
|
190
190
|
else
|
191
191
|
f.puts "agents=#{@runtime_dirs[:support_dir]}"
|
192
192
|
end
|
193
|
+
f.puts "libdir=#{PhusionPassenger.lib_dir}"
|
193
194
|
f.puts "helper_scripts=#{PhusionPassenger.helper_scripts_dir}"
|
194
195
|
f.puts "resources=#{PhusionPassenger.resources_dir}"
|
196
|
+
f.puts "includedir=#{PhusionPassenger.include_dir}"
|
195
197
|
f.puts "doc=#{PhusionPassenger.doc_dir}"
|
196
198
|
f.puts "rubylib=#{PhusionPassenger.ruby_libdir}"
|
197
199
|
f.puts "apache2_module=#{PhusionPassenger.apache2_module_path}"
|
@@ -95,7 +95,7 @@ protected
|
|
95
95
|
'g++',
|
96
96
|
'gmake',
|
97
97
|
'download-tool',
|
98
|
-
'ruby-dev',
|
98
|
+
PlatformInfo.passenger_needs_ruby_dev_header? ? 'ruby-dev' : nil,
|
99
99
|
'ruby-openssl',
|
100
100
|
'rubygems',
|
101
101
|
'rake',
|
@@ -105,7 +105,7 @@ protected
|
|
105
105
|
'zlib-dev',
|
106
106
|
'pcre-dev',
|
107
107
|
'daemon_controller >= 1.1.0'
|
108
|
-
]
|
108
|
+
].compact
|
109
109
|
return [specs, ids]
|
110
110
|
end
|
111
111
|
|
@@ -529,7 +529,8 @@ private
|
|
529
529
|
nginx_libs = COMMON_LIBRARY.only(*NGINX_LIBS_SELECTOR).
|
530
530
|
set_output_dir(output_dir).
|
531
531
|
link_objects_as_string
|
532
|
-
command << "env
|
532
|
+
command << "env PASSENGER_INCLUDEDIR='#{PhusionPassenger.include_dir}'" <<
|
533
|
+
" PASSENGER_LIBS='#{nginx_libs} #{output_dir}/../libboost_oxt.a' "
|
533
534
|
end
|
534
535
|
# RPM thinks it's being smart by scanning binaries for
|
535
536
|
# paths and refusing to create package if it detects any
|
@@ -42,7 +42,7 @@ class StartCommand < Command
|
|
42
42
|
def self.description
|
43
43
|
return "Start Phusion Passenger Standalone."
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
def initialize(args)
|
47
47
|
super(args)
|
48
48
|
@console_mutex = Mutex.new
|
@@ -51,11 +51,11 @@ class StartCommand < Command
|
|
51
51
|
@interruptable_threads = []
|
52
52
|
@plugin = PhusionPassenger::Plugin.new('standalone/start_command', self, @options)
|
53
53
|
end
|
54
|
-
|
54
|
+
|
55
55
|
def run
|
56
56
|
parse_my_options
|
57
57
|
sanity_check_options
|
58
|
-
|
58
|
+
|
59
59
|
@runtime_dirs = determine_runtime_dirs
|
60
60
|
ensure_nginx_installed
|
61
61
|
determine_various_resource_locations
|
@@ -63,15 +63,21 @@ class StartCommand < Command
|
|
63
63
|
@app_finder = AppFinder.new(@args, @options)
|
64
64
|
@apps = @app_finder.scan
|
65
65
|
@plugin.call_hook(:found_apps, @apps)
|
66
|
-
|
66
|
+
|
67
67
|
extra_controller_options = {}
|
68
68
|
@plugin.call_hook(:before_creating_nginx_controller, extra_controller_options)
|
69
69
|
create_nginx_controller(extra_controller_options)
|
70
|
-
|
70
|
+
|
71
71
|
begin
|
72
72
|
start_nginx
|
73
73
|
show_intro_message
|
74
|
-
|
74
|
+
if @options[:daemonize]
|
75
|
+
if PlatformInfo.ruby_supports_fork?
|
76
|
+
daemonize
|
77
|
+
else
|
78
|
+
daemonize_without_fork
|
79
|
+
end
|
80
|
+
end
|
75
81
|
Thread.abort_on_exception = true
|
76
82
|
@plugin.call_hook(:nginx_started, @nginx)
|
77
83
|
########################
|
@@ -108,7 +114,7 @@ private
|
|
108
114
|
def require_file_utils
|
109
115
|
require 'fileutils' unless defined?(FileUtils)
|
110
116
|
end
|
111
|
-
|
117
|
+
|
112
118
|
def parse_my_options
|
113
119
|
description = "Starts Phusion Passenger Standalone and serve one or more Ruby web applications."
|
114
120
|
parse_options!("start [directory]", description) do |opts|
|
@@ -126,7 +132,7 @@ private
|
|
126
132
|
wrap_desc("Bind to Unix domain socket instead of TCP socket")) do |value|
|
127
133
|
@options[:socket_file] = value
|
128
134
|
end
|
129
|
-
|
135
|
+
|
130
136
|
opts.separator ""
|
131
137
|
opts.on("-e", "--environment ENV", String,
|
132
138
|
wrap_desc("Framework environment (default: #{@options[:env]})")) do |value|
|
@@ -168,14 +174,14 @@ private
|
|
168
174
|
wrap_desc("Specify Union Station key")) do |value|
|
169
175
|
@options[:union_station_key] = value
|
170
176
|
end
|
171
|
-
|
177
|
+
|
172
178
|
opts.separator ""
|
173
179
|
opts.on("--ping-port NUMBER", Integer,
|
174
180
|
wrap_desc("Use the given port number for checking whether Nginx is alive (default: same as the normal port)")) do |value|
|
175
181
|
@options[:ping_port] = value
|
176
182
|
end
|
177
183
|
@plugin.call_hook(:parse_options, opts)
|
178
|
-
|
184
|
+
|
179
185
|
opts.separator ""
|
180
186
|
opts.on("-d", "--daemonize",
|
181
187
|
wrap_desc("Daemonize into the background")) do
|
@@ -218,7 +224,7 @@ private
|
|
218
224
|
end
|
219
225
|
@plugin.call_hook(:done_parsing_options)
|
220
226
|
end
|
221
|
-
|
227
|
+
|
222
228
|
def sanity_check_options
|
223
229
|
if @options[:tcp_explicitly_given] && @options[:socket_file]
|
224
230
|
error "You cannot specify both --address/--port and --socket. Please choose either one."
|
@@ -227,7 +233,7 @@ private
|
|
227
233
|
check_port_bind_permission_and_display_sudo_suggestion
|
228
234
|
check_port_availability
|
229
235
|
end
|
230
|
-
|
236
|
+
|
231
237
|
# Most platforms don't allow non-root processes to bind to a port lower than 1024.
|
232
238
|
# Check whether this is the case for the current platform and if so, tell the user
|
233
239
|
# that it must re-run Phusion Passenger Standalone with sudo.
|
@@ -241,9 +247,9 @@ private
|
|
241
247
|
error "Only the 'root' user can run this program on port #{@options[:port]}. " <<
|
242
248
|
"You are currently running as '#{myself}'. Please re-run this program " <<
|
243
249
|
"with root privileges with the following command:\n\n" <<
|
244
|
-
|
250
|
+
|
245
251
|
" #{PlatformInfo.ruby_sudo_command} passenger start #{@original_args.join(' ')} --user=#{myself}\n\n" <<
|
246
|
-
|
252
|
+
|
247
253
|
"Don't forget the '--user' part! That will make Phusion Passenger Standalone " <<
|
248
254
|
"drop root privileges and switch to '#{myself}' after it has obtained " <<
|
249
255
|
"port #{@options[:port]}."
|
@@ -254,7 +260,7 @@ private
|
|
254
260
|
|
255
261
|
if defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby"
|
256
262
|
require 'java'
|
257
|
-
|
263
|
+
|
258
264
|
def check_port(host_name, port)
|
259
265
|
channel = java.nio.channels.SocketChannel.open
|
260
266
|
begin
|
@@ -278,7 +284,7 @@ private
|
|
278
284
|
throw e
|
279
285
|
end
|
280
286
|
end
|
281
|
-
|
287
|
+
|
282
288
|
# Not done connecting and no error.
|
283
289
|
sleep 0.01
|
284
290
|
if Time.now.to_f >= deadline
|
@@ -320,7 +326,7 @@ private
|
|
320
326
|
end
|
321
327
|
end
|
322
328
|
end
|
323
|
-
|
329
|
+
|
324
330
|
def check_port_availability
|
325
331
|
if !@options[:socket_file] && check_port(@options[:address], @options[:port])
|
326
332
|
error "The address #{@options[:address]}:#{@options[:port]} is already " <<
|
@@ -332,11 +338,11 @@ private
|
|
332
338
|
exit 1
|
333
339
|
end
|
334
340
|
end
|
335
|
-
|
341
|
+
|
336
342
|
def should_watch_logs?
|
337
343
|
return !@options[:daemonize] && @options[:log_file] != "/dev/null"
|
338
344
|
end
|
339
|
-
|
345
|
+
|
340
346
|
# Returns the URL that Nginx will be listening on.
|
341
347
|
def listen_url
|
342
348
|
if @options[:socket_file]
|
@@ -350,7 +356,7 @@ private
|
|
350
356
|
return result
|
351
357
|
end
|
352
358
|
end
|
353
|
-
|
359
|
+
|
354
360
|
def install_runtime(runtime_dirs)
|
355
361
|
require 'phusion_passenger/standalone/runtime_installer'
|
356
362
|
installer = RuntimeInstaller.new(
|
@@ -364,7 +370,7 @@ private
|
|
364
370
|
:plugin => @plugin)
|
365
371
|
installer.run
|
366
372
|
end
|
367
|
-
|
373
|
+
|
368
374
|
def determine_runtime_dirs
|
369
375
|
require_platform_info_binary_compatibility
|
370
376
|
if root = @options[:runtime_dir]
|
@@ -405,7 +411,7 @@ private
|
|
405
411
|
end
|
406
412
|
end
|
407
413
|
end
|
408
|
-
|
414
|
+
|
409
415
|
def start_nginx
|
410
416
|
begin
|
411
417
|
@nginx.start
|
@@ -426,15 +432,15 @@ private
|
|
426
432
|
exit 1
|
427
433
|
end
|
428
434
|
end
|
429
|
-
|
435
|
+
|
430
436
|
def show_intro_message
|
431
437
|
puts "=============== Phusion Passenger Standalone web server started ==============="
|
432
438
|
puts "PID file: #{@options[:pid_file]}"
|
433
439
|
puts "Log file: #{@options[:log_file]}"
|
434
440
|
puts "Environment: #{@options[:env]}"
|
435
|
-
|
441
|
+
|
436
442
|
puts "Accessible via: #{listen_url}"
|
437
|
-
|
443
|
+
|
438
444
|
puts
|
439
445
|
if @options[:daemonize]
|
440
446
|
puts "Serving in the background as a daemon."
|
@@ -443,7 +449,13 @@ private
|
|
443
449
|
end
|
444
450
|
puts "==============================================================================="
|
445
451
|
end
|
446
|
-
|
452
|
+
|
453
|
+
def daemonize_without_fork
|
454
|
+
STDERR.puts "Unable to daemonize using the current Ruby interpreter " +
|
455
|
+
"(#{PlatformInfo.ruby_command}) because it does not support forking."
|
456
|
+
exit 1
|
457
|
+
end
|
458
|
+
|
447
459
|
def daemonize
|
448
460
|
pid = fork
|
449
461
|
if pid
|
@@ -460,7 +472,7 @@ private
|
|
460
472
|
Process.setsid
|
461
473
|
end
|
462
474
|
end
|
463
|
-
|
475
|
+
|
464
476
|
# Wait until the termination pipe becomes readable (a hint for threads
|
465
477
|
# to shut down), or until the timeout has been reached. Returns true if
|
466
478
|
# the termination pipe became readable, false if the timeout has been reached.
|
@@ -468,7 +480,7 @@ private
|
|
468
480
|
ios = select([@termination_pipe[0]], nil, nil, timeout)
|
469
481
|
return !ios.nil?
|
470
482
|
end
|
471
|
-
|
483
|
+
|
472
484
|
def watch_log_file(log_file)
|
473
485
|
if File.exist?(log_file)
|
474
486
|
backward = 0
|
@@ -479,7 +491,7 @@ private
|
|
479
491
|
end
|
480
492
|
backward = 10
|
481
493
|
end
|
482
|
-
|
494
|
+
|
483
495
|
IO.popen("tail -f -n #{backward} \"#{log_file}\"", "rb") do |f|
|
484
496
|
begin
|
485
497
|
while true
|
@@ -498,7 +510,7 @@ private
|
|
498
510
|
end
|
499
511
|
end
|
500
512
|
end
|
501
|
-
|
513
|
+
|
502
514
|
def watch_log_files_in_background
|
503
515
|
@apps.each do |app|
|
504
516
|
thread = Thread.new do
|
@@ -513,7 +525,7 @@ private
|
|
513
525
|
@threads << thread
|
514
526
|
@interruptable_threads << thread
|
515
527
|
end
|
516
|
-
|
528
|
+
|
517
529
|
def wait_until_nginx_has_exited
|
518
530
|
# Since Nginx is not our child process (it daemonizes or we daemonize)
|
519
531
|
# we cannot use Process.waitpid to wait for it. A busy-sleep-loop with
|
@@ -535,7 +547,7 @@ private
|
|
535
547
|
end
|
536
548
|
rescue Errno::ECONNREFUSED, Errno::ECONNRESET
|
537
549
|
end
|
538
|
-
|
550
|
+
|
539
551
|
def stop_nginx
|
540
552
|
@console_mutex.synchronize do
|
541
553
|
STDOUT.write("Stopping web server...")
|
@@ -545,7 +557,7 @@ private
|
|
545
557
|
STDOUT.flush
|
546
558
|
end
|
547
559
|
end
|
548
|
-
|
560
|
+
|
549
561
|
def stop_threads
|
550
562
|
if !@termination_pipe[1].closed?
|
551
563
|
@termination_pipe[1].write("x")
|
@@ -560,9 +572,9 @@ private
|
|
560
572
|
end
|
561
573
|
@threads = []
|
562
574
|
end
|
563
|
-
|
575
|
+
|
564
576
|
#### Config file template helpers ####
|
565
|
-
|
577
|
+
|
566
578
|
def nginx_listen_address(options = @options, for_ping_port = false)
|
567
579
|
if options[:socket_file]
|
568
580
|
return "unix:" + File.expand_path(options[:socket_file])
|
@@ -575,13 +587,13 @@ private
|
|
575
587
|
return "#{options[:address]}:#{port}"
|
576
588
|
end
|
577
589
|
end
|
578
|
-
|
590
|
+
|
579
591
|
def default_group_for(username)
|
580
592
|
user = Etc.getpwnam(username)
|
581
593
|
group = Etc.getgrgid(user.gid)
|
582
594
|
return group.name
|
583
595
|
end
|
584
|
-
|
596
|
+
|
585
597
|
#################
|
586
598
|
end
|
587
599
|
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<red><b>The PCRE checksum could not be verified</b></red>
|
2
|
+
|
3
|
+
Nginx requires PCRE for its rewrite module, so this installer will attempt to
|
4
|
+
install Nginx without the rewrite module.
|
5
|
+
|
6
|
+
If you want to make use of Nginx's rewrite module, please install PCRE manually
|
7
|
+
by downloading it from:
|
8
|
+
|
9
|
+
http://www.pcre.org/
|
10
|
+
|
11
|
+
Press ENTER to continue, or Ctrl-C to abort.
|