passenger 5.0.0.beta3 → 5.0.0.rc1
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.
- checksums.yaml +8 -8
- checksums.yaml.gz.asc +7 -7
- data.tar.gz.asc +7 -7
- data/.editorconfig +11 -5
- data/CHANGELOG +38 -0
- data/CONTRIBUTING.md +1 -4
- data/Gemfile +0 -1
- data/Gemfile.lock +0 -2
- data/Rakefile +33 -33
- data/bin/passenger +1 -1
- data/bin/passenger-config +1 -1
- data/bin/passenger-install-apache2-module +800 -800
- data/bin/passenger-install-nginx-module +592 -592
- data/bin/passenger-memory-stats +127 -127
- data/bin/passenger-status +216 -216
- data/build/agents.rb +127 -127
- data/build/apache2.rb +87 -87
- data/build/basics.rb +60 -60
- data/build/common_library.rb +165 -165
- data/build/cplusplus_support.rb +51 -51
- data/build/cxx_tests.rb +268 -268
- data/build/debian.rb +143 -143
- data/build/documentation.rb +58 -58
- data/build/integration_tests.rb +81 -81
- data/build/misc.rb +132 -132
- data/build/nginx.rb +20 -20
- data/build/node_tests.rb +7 -7
- data/build/oxt_tests.rb +14 -14
- data/build/packaging.rb +570 -570
- data/build/preprocessor.rb +260 -260
- data/build/rake_extensions.rb +71 -71
- data/build/ruby_extension.rb +29 -29
- data/build/ruby_tests.rb +6 -6
- data/build/test_basics.rb +37 -37
- data/debian.template/control.template +3 -5
- data/dev/copy_boost_headers +134 -134
- data/dev/install_scripts_bootstrap_code.rb +25 -25
- data/dev/list_tests +20 -20
- data/dev/ruby_server.rb +223 -223
- data/dev/runner +18 -18
- data/doc/ServerOptimizationGuide.txt.md +55 -2
- data/doc/Users guide Nginx.txt +0 -26
- data/doc/Users guide Standalone.txt +5 -1
- data/doc/users_guide_snippets/tips.txt +9 -0
- data/ext/common/ApplicationPool2/Group.h +23 -11
- data/ext/common/ApplicationPool2/Implementation.cpp +32 -7
- data/ext/common/ApplicationPool2/Pool.h +22 -17
- data/ext/common/ApplicationPool2/SmartSpawner.h +4 -1
- data/ext/common/ApplicationPool2/Spawner.h +1 -1
- data/ext/common/Constants.h +1 -1
- data/ext/common/agents/Base.cpp +35 -20
- data/ext/common/agents/HelperAgent/Main.cpp +8 -1
- data/ext/common/agents/HelperAgent/OptionParser.h +18 -4
- data/ext/common/agents/HelperAgent/RequestHandler.h +2 -83
- data/ext/common/agents/HelperAgent/RequestHandler/ForwardResponse.cpp +54 -1
- data/ext/common/agents/HelperAgent/RequestHandler/InitRequest.cpp +7 -4
- data/ext/common/agents/Main.cpp +1 -1
- data/ext/common/agents/Watchdog/Main.cpp +54 -19
- data/ext/nginx/Configuration.c +7 -0
- data/ext/nginx/ContentHandler.c +9 -1
- data/helper-scripts/backtrace-sanitizer.rb +106 -87
- data/helper-scripts/crash-watch.rb +32 -0
- data/helper-scripts/download_binaries/extconf.rb +38 -38
- data/helper-scripts/meteor-loader.rb +107 -107
- data/helper-scripts/prespawn +101 -101
- data/helper-scripts/rack-loader.rb +96 -96
- data/helper-scripts/rack-preloader.rb +137 -137
- data/lib/phusion_passenger.rb +292 -292
- data/lib/phusion_passenger/abstract_installer.rb +438 -438
- data/lib/phusion_passenger/active_support3_extensions/init.rb +168 -170
- data/lib/phusion_passenger/admin_tools.rb +20 -20
- data/lib/phusion_passenger/admin_tools/instance.rb +178 -178
- data/lib/phusion_passenger/admin_tools/instance_registry.rb +61 -61
- data/lib/phusion_passenger/admin_tools/memory_stats.rb +267 -267
- data/lib/phusion_passenger/apache2/config_options.rb +182 -182
- data/lib/phusion_passenger/common_library.rb +479 -485
- data/lib/phusion_passenger/config/about_command.rb +161 -161
- data/lib/phusion_passenger/config/admin_command_command.rb +129 -129
- data/lib/phusion_passenger/config/agent_compiler.rb +121 -121
- data/lib/phusion_passenger/config/build_native_support_command.rb +43 -43
- data/lib/phusion_passenger/config/command.rb +25 -25
- data/lib/phusion_passenger/config/compile_agent_command.rb +62 -62
- data/lib/phusion_passenger/config/compile_nginx_engine_command.rb +88 -73
- data/lib/phusion_passenger/config/detach_process_command.rb +72 -72
- data/lib/phusion_passenger/config/download_agent_command.rb +246 -227
- data/lib/phusion_passenger/config/download_nginx_engine_command.rb +245 -224
- data/lib/phusion_passenger/config/install_agent_command.rb +144 -132
- data/lib/phusion_passenger/config/install_standalone_runtime_command.rb +205 -185
- data/lib/phusion_passenger/config/installation_utils.rb +204 -204
- data/lib/phusion_passenger/config/list_instances_command.rb +64 -64
- data/lib/phusion_passenger/config/main.rb +152 -152
- data/lib/phusion_passenger/config/nginx_engine_compiler.rb +319 -300
- data/lib/phusion_passenger/config/reopen_logs_command.rb +67 -67
- data/lib/phusion_passenger/config/restart_app_command.rb +155 -155
- data/lib/phusion_passenger/config/system_metrics_command.rb +13 -13
- data/lib/phusion_passenger/config/utils.rb +95 -95
- data/lib/phusion_passenger/config/validate_install_command.rb +198 -198
- data/lib/phusion_passenger/console_text_template.rb +25 -25
- data/lib/phusion_passenger/constants.rb +90 -90
- data/lib/phusion_passenger/debug_logging.rb +106 -106
- data/lib/phusion_passenger/loader_shared_helpers.rb +447 -432
- data/lib/phusion_passenger/message_channel.rb +312 -312
- data/lib/phusion_passenger/message_client.rb +176 -176
- data/lib/phusion_passenger/native_support.rb +369 -369
- data/lib/phusion_passenger/nginx/config_options.rb +297 -297
- data/lib/phusion_passenger/packaging.rb +131 -131
- data/lib/phusion_passenger/platform_info.rb +360 -360
- data/lib/phusion_passenger/platform_info/apache.rb +767 -767
- data/lib/phusion_passenger/platform_info/apache_detector.rb +199 -199
- data/lib/phusion_passenger/platform_info/binary_compatibility.rb +107 -107
- data/lib/phusion_passenger/platform_info/compiler.rb +570 -570
- data/lib/phusion_passenger/platform_info/curl.rb +32 -32
- data/lib/phusion_passenger/platform_info/cxx_portability.rb +188 -188
- data/lib/phusion_passenger/platform_info/depcheck.rb +372 -372
- data/lib/phusion_passenger/platform_info/depcheck_specs/apache2.rb +109 -109
- data/lib/phusion_passenger/platform_info/depcheck_specs/compiler_toolchain.rb +4 -4
- data/lib/phusion_passenger/platform_info/depcheck_specs/gems.rb +10 -34
- data/lib/phusion_passenger/platform_info/depcheck_specs/libs.rb +101 -101
- data/lib/phusion_passenger/platform_info/depcheck_specs/ruby.rb +5 -5
- data/lib/phusion_passenger/platform_info/depcheck_specs/utilities.rb +13 -13
- data/lib/phusion_passenger/platform_info/linux.rb +55 -55
- data/lib/phusion_passenger/platform_info/operating_system.rb +149 -149
- data/lib/phusion_passenger/platform_info/ruby.rb +468 -448
- data/lib/phusion_passenger/platform_info/zlib.rb +9 -9
- data/lib/phusion_passenger/plugin.rb +66 -66
- data/lib/phusion_passenger/preloader_shared_helpers.rb +126 -126
- data/lib/phusion_passenger/public_api.rb +191 -191
- data/lib/phusion_passenger/rack/out_of_band_gc.rb +93 -94
- data/lib/phusion_passenger/rack/thread_handler_extension.rb +231 -227
- data/lib/phusion_passenger/request_handler.rb +567 -577
- data/lib/phusion_passenger/request_handler/thread_handler.rb +379 -381
- data/lib/phusion_passenger/ruby_core_enhancements.rb +86 -86
- data/lib/phusion_passenger/ruby_core_io_enhancements.rb +74 -74
- data/lib/phusion_passenger/simple_benchmarking.rb +25 -25
- data/lib/phusion_passenger/standalone/app_finder.rb +153 -150
- data/lib/phusion_passenger/standalone/command.rb +44 -40
- data/lib/phusion_passenger/standalone/config_utils.rb +53 -53
- data/lib/phusion_passenger/standalone/control_utils.rb +38 -59
- data/lib/phusion_passenger/standalone/main.rb +73 -73
- data/lib/phusion_passenger/standalone/start_command.rb +697 -685
- data/lib/phusion_passenger/standalone/start_command/builtin_engine.rb +193 -155
- data/lib/phusion_passenger/standalone/start_command/nginx_engine.rb +162 -133
- data/lib/phusion_passenger/standalone/status_command.rb +64 -64
- data/lib/phusion_passenger/standalone/stop_command.rb +72 -72
- data/lib/phusion_passenger/standalone/version_command.rb +9 -9
- data/lib/phusion_passenger/union_station/connection.rb +32 -32
- data/lib/phusion_passenger/union_station/core.rb +251 -251
- data/lib/phusion_passenger/union_station/transaction.rb +126 -126
- data/lib/phusion_passenger/utils.rb +199 -167
- data/lib/phusion_passenger/utils/ansi_colors.rb +128 -128
- data/lib/phusion_passenger/utils/download.rb +196 -196
- data/lib/phusion_passenger/utils/file_system_watcher.rb +158 -158
- data/lib/phusion_passenger/utils/hosts_file_parser.rb +101 -101
- data/lib/phusion_passenger/utils/lock.rb +31 -31
- data/lib/phusion_passenger/utils/native_support_utils.rb +31 -31
- data/lib/phusion_passenger/utils/progress_bar.rb +26 -26
- data/lib/phusion_passenger/utils/shellwords.rb +20 -20
- data/lib/phusion_passenger/utils/terminal_choice_menu.rb +206 -206
- data/lib/phusion_passenger/utils/unseekable_socket.rb +272 -272
- data/lib/phusion_passenger/vendor/crash_watch/app.rb +129 -0
- data/lib/phusion_passenger/vendor/crash_watch/gdb_controller.rb +341 -0
- data/lib/phusion_passenger/vendor/crash_watch/version.rb +24 -0
- data/lib/phusion_passenger/vendor/daemon_controller.rb +877 -0
- data/lib/phusion_passenger/vendor/daemon_controller/lock_file.rb +127 -0
- data/lib/phusion_passenger/vendor/daemon_controller/spawn.rb +26 -0
- data/lib/phusion_passenger/vendor/daemon_controller/version.rb +29 -0
- data/packaging/rpm/passenger_spec/passenger.spec.template +0 -1
- data/passenger.gemspec +0 -1
- data/resources/templates/config/nginx_engine_compiler/possible_solutions_for_download_and_extraction_problems.txt.erb +27 -0
- data/resources/templates/standalone/config.erb +19 -15
- data/test/integration_tests/apache2_tests.rb +566 -566
- data/test/integration_tests/downloaded_binaries_tests.rb +126 -125
- data/test/integration_tests/native_packaging_spec.rb +296 -296
- data/test/integration_tests/nginx_tests.rb +393 -393
- data/test/integration_tests/shared/example_webapp_tests.rb +282 -280
- data/test/integration_tests/source_packaging_test.rb +138 -138
- data/test/integration_tests/spec_helper.rb +5 -5
- data/test/integration_tests/standalone_tests.rb +367 -367
- data/test/ruby/debug_logging_spec.rb +133 -133
- data/test/ruby/message_channel_spec.rb +186 -186
- data/test/ruby/rack/loader_spec.rb +28 -28
- data/test/ruby/rack/preloader_spec.rb +34 -34
- data/test/ruby/rails3.0/loader_spec.rb +12 -12
- data/test/ruby/rails3.0/preloader_spec.rb +18 -18
- data/test/ruby/rails3.1/loader_spec.rb +12 -12
- data/test/ruby/rails3.1/preloader_spec.rb +18 -18
- data/test/ruby/rails3.2/loader_spec.rb +12 -12
- data/test/ruby/rails3.2/preloader_spec.rb +18 -18
- data/test/ruby/rails4.0/loader_spec.rb +12 -12
- data/test/ruby/rails4.0/preloader_spec.rb +18 -18
- data/test/ruby/rails4.1/loader_spec.rb +12 -12
- data/test/ruby/rails4.1/preloader_spec.rb +18 -18
- data/test/ruby/request_handler_spec.rb +730 -730
- data/test/ruby/shared/loader_sharedspec.rb +224 -224
- data/test/ruby/shared/rails/union_station_extensions_sharedspec.rb +327 -327
- data/test/ruby/shared/ruby_loader_sharedspec.rb +47 -47
- data/test/ruby/spec_helper.rb +65 -65
- data/test/ruby/standalone/runtime_installer_spec.rb +384 -384
- data/test/ruby/union_station_spec.rb +276 -276
- data/test/ruby/utils/file_system_watcher_spec.rb +220 -220
- data/test/ruby/utils/hosts_file_parser.rb +248 -248
- data/test/ruby/utils/tee_input_spec.rb +215 -215
- data/test/ruby/utils/unseekable_socket_spec.rb +57 -57
- data/test/ruby/utils_spec.rb +21 -21
- data/test/stub/rack/config.ru +87 -87
- data/test/stub/rack/library.rb +8 -8
- data/test/stub/rack/start.rb +30 -30
- data/test/support/apache2_controller.rb +191 -191
- data/test/support/nginx_controller.rb +90 -99
- data/test/support/placebo-preloader.rb +57 -57
- data/test/support/test_helper.rb +435 -435
- metadata +11 -21
- metadata.gz.asc +7 -7
- data/lib/phusion_passenger/standalone/command2.rb +0 -292
- data/lib/phusion_passenger/standalone/start2_command.rb +0 -799
- data/resources/templates/standalone/download_tool_missing.txt.erb +0 -18
- data/resources/templates/standalone/possible_solutions_for_download_and_extraction_problems.txt.erb +0 -17
- data/resources/templates/standalone/run_installer_as_root.txt.erb +0 -8
@@ -26,73 +26,73 @@ require 'fileutils'
|
|
26
26
|
PhusionPassenger.require_passenger_lib 'admin_tools/instance'
|
27
27
|
|
28
28
|
module PhusionPassenger
|
29
|
-
module AdminTools
|
29
|
+
module AdminTools
|
30
30
|
|
31
|
-
class InstanceRegistry
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
class InstanceRegistry
|
32
|
+
def initialize(path = nil)
|
33
|
+
@path = path || default_path
|
34
|
+
end
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
36
|
+
def list(options = {})
|
37
|
+
options = {
|
38
|
+
:clean_stale_or_corrupted => true
|
39
|
+
}.merge(options)
|
40
|
+
instances = []
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
42
|
+
Dir["#{@path}/passenger.*"].each do |dir|
|
43
|
+
instance = Instance.new(dir)
|
44
|
+
case instance.state
|
45
|
+
when :good
|
46
|
+
if instance.locked?
|
47
|
+
instances << instance
|
48
|
+
elsif options[:clean_stale_or_corrupted]
|
49
|
+
cleanup(dir)
|
50
|
+
end
|
51
|
+
when :structure_version_unsupported
|
52
|
+
next
|
53
|
+
when :corrupted
|
54
|
+
if !instance.locked? && options[:clean_stale_or_corrupted]
|
55
|
+
cleanup(dir)
|
56
|
+
end
|
57
|
+
when :not_finalized
|
58
|
+
if instance.stale? && options[:clean_stale_or_corrupted]
|
59
|
+
cleanup(dir)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
return instances
|
64
|
+
end
|
65
65
|
|
66
|
-
|
67
|
-
|
68
|
-
|
66
|
+
def find_by_name(name, options = {})
|
67
|
+
return list(options).find { |instance| instance.name == name }
|
68
|
+
end
|
69
69
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
70
|
+
def find_by_name_prefix(name, options = {})
|
71
|
+
prefix = /^#{Regexp.escape name}/
|
72
|
+
results = list(options).find_all { |instance| instance.name =~ prefix }
|
73
|
+
if results.size <= 1
|
74
|
+
return results.first
|
75
|
+
else
|
76
|
+
return :ambiguous
|
77
|
+
end
|
78
|
+
end
|
79
79
|
|
80
|
-
private
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
80
|
+
private
|
81
|
+
def default_path
|
82
|
+
["PASSENGER_INSTANCE_REGISTRY_DIR", "TMPDIR"].each do |name|
|
83
|
+
if ENV.has_key?(name) && !ENV[name].empty?
|
84
|
+
return ENV[name]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
return "/tmp"
|
88
|
+
end
|
89
89
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
end
|
90
|
+
def cleanup(path)
|
91
|
+
puts "*** Cleaning stale instance directory #{path}"
|
92
|
+
FileUtils.chmod_R(0700, path) rescue nil
|
93
|
+
FileUtils.remove_entry_secure(path)
|
94
|
+
end
|
95
|
+
end
|
96
96
|
|
97
|
-
end # module AdminTools
|
97
|
+
end # module AdminTools
|
98
98
|
end # module PhusionPassenger
|
@@ -25,276 +25,276 @@ PhusionPassenger.require_passenger_lib 'platform_info/apache'
|
|
25
25
|
PhusionPassenger.require_passenger_lib 'platform_info/operating_system'
|
26
26
|
|
27
27
|
module PhusionPassenger
|
28
|
-
module AdminTools
|
28
|
+
module AdminTools
|
29
29
|
|
30
|
-
class MemoryStats
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
def vm_size_in_mb
|
43
|
-
return sprintf("%.1f MB", vm_size / 1024.0)
|
44
|
-
end
|
30
|
+
class MemoryStats
|
31
|
+
# Information about a single process.
|
32
|
+
class Process
|
33
|
+
attr_accessor :pid
|
34
|
+
attr_accessor :ppid
|
35
|
+
attr_accessor :threads
|
36
|
+
attr_accessor :vm_size # in KB
|
37
|
+
attr_accessor :rss # in KB
|
38
|
+
attr_accessor :cpu
|
39
|
+
attr_accessor :name
|
40
|
+
attr_accessor :private_dirty_rss # in KB
|
45
41
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
def private_dirty_rss_in_mb
|
51
|
-
if private_dirty_rss.is_a?(Numeric)
|
52
|
-
return sprintf("%.1f MB", private_dirty_rss / 1024.0)
|
53
|
-
else
|
54
|
-
return "?"
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def to_a
|
59
|
-
return [pid, ppid, vm_size_in_mb, private_dirty_rss_in_mb, rss_in_mb, name]
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
# Returns a list of Apache processes, which may be the empty list if Apache is
|
64
|
-
# not running. If the Apache executable name is unknown then nil will be returned.
|
65
|
-
def apache_processes
|
66
|
-
@apache_processes ||= begin
|
67
|
-
if PlatformInfo.httpd
|
68
|
-
processes = list_processes(:exe => PlatformInfo.httpd)
|
69
|
-
if processes.empty?
|
70
|
-
# On some Linux distros, the Apache worker processes
|
71
|
-
# are called "httpd.worker"
|
72
|
-
processes = list_processes(:exe => "#{PlatformInfo.httpd}.worker")
|
73
|
-
end
|
74
|
-
processes
|
75
|
-
else
|
76
|
-
nil
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
# Returns a list of Nginx processes, which may be the empty list if
|
82
|
-
# Nginx is not running.
|
83
|
-
def nginx_processes
|
84
|
-
@nginx_processes ||= list_processes(:exe => "nginx")
|
85
|
-
end
|
86
|
-
|
87
|
-
# Returns a list of Phusion Passenger processes, which may be the empty list if
|
88
|
-
# Phusion Passenger is not running.
|
89
|
-
def passenger_processes
|
90
|
-
@passenger_processes ||= list_processes(:match =>
|
91
|
-
/((^| )Passenger|(^| )Rails:|(^| )Rack:|wsgi-loader.py)/)
|
92
|
-
end
|
93
|
-
|
94
|
-
# Returns the sum of the memory usages of all given processes.
|
95
|
-
# Returns a pair [usage, accurate]. +usage+ is the summed memory usage in KB,
|
96
|
-
# and +accurate+ indicates whether this sum is accurate. This may be false
|
97
|
-
# if some process's memory usage cannot be determined.
|
98
|
-
def sum_memory_usage(processes)
|
99
|
-
total = 0
|
100
|
-
if should_show_private_dirty_rss?
|
101
|
-
accurate = true
|
102
|
-
processes.each do |p|
|
103
|
-
if p.private_dirty_rss.is_a?(Numeric)
|
104
|
-
total += p.private_dirty_rss
|
105
|
-
else
|
106
|
-
accurate = true
|
107
|
-
end
|
108
|
-
end
|
109
|
-
return [total, accurate]
|
110
|
-
else
|
111
|
-
processes.each do |p|
|
112
|
-
total += p.rss
|
113
|
-
end
|
114
|
-
return [total, true]
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
def platform_provides_private_dirty_rss_information?
|
119
|
-
return os_name == "linux"
|
120
|
-
end
|
121
|
-
|
122
|
-
# Returns whether root privileges are required in order to measure private dirty RSS.
|
123
|
-
# Only meaningful if #platform_provides_private_dirty_rss_information? returns true.
|
124
|
-
def root_privileges_required_for_private_dirty_rss?
|
125
|
-
all_processes = (apache_processes || []) + nginx_processes + passenger_processes
|
126
|
-
return all_processes.any?{ |p| p.private_dirty_rss.nil? }
|
127
|
-
end
|
128
|
-
|
129
|
-
def should_show_private_dirty_rss?
|
130
|
-
return platform_provides_private_dirty_rss_information? &&
|
131
|
-
(::Process.euid == 0 || root_privileges_required_for_private_dirty_rss?)
|
132
|
-
end
|
133
|
-
|
134
|
-
# Determine the system's RAM usage, not including swap.
|
135
|
-
# Returns a tuple [total, used] where both numbers are in KB, or nil
|
136
|
-
# if the system's RAM usage cannot be determined.
|
137
|
-
def system_ram_usage
|
138
|
-
@total_system_ram ||= begin
|
139
|
-
case os_name
|
140
|
-
when /linux/
|
141
|
-
free_text = `free -k`
|
142
|
-
|
143
|
-
free_text =~ %r{Mem:(.+)$}
|
144
|
-
line = $1.strip
|
145
|
-
total = line.split(/ +/).first.to_i
|
146
|
-
|
147
|
-
free_text =~ %r{buffers/cache:(.+)$}
|
148
|
-
line = $1.strip
|
149
|
-
used = line.split(/ +/).first.to_i
|
150
|
-
|
151
|
-
[total, used]
|
152
|
-
when /macosx/
|
153
|
-
vm_stat = `vm_stat`
|
154
|
-
vm_stat =~ /page size of (\d+) bytes/
|
155
|
-
page_size = $1
|
156
|
-
vm_stat =~ /Pages free: +(\d+)/
|
157
|
-
free = $1
|
158
|
-
vm_stat =~ /Pages active: +(\d+)/
|
159
|
-
active = $1
|
160
|
-
vm_stat =~ /Pages inactive: +(\d+)/
|
161
|
-
inactive = $1
|
162
|
-
vm_stat =~ /Pages wired down: +(\d+)/
|
163
|
-
wired = $1
|
164
|
-
|
165
|
-
if page_size && free && active && inactive && wired
|
166
|
-
page_size = page_size.to_i
|
167
|
-
free = free.to_i * page_size / 1024
|
168
|
-
active = active.to_i * page_size / 1024
|
169
|
-
inactive = inactive.to_i * page_size / 1024
|
170
|
-
wired = wired.to_i * page_size / 1024
|
171
|
-
|
172
|
-
used = active + wired
|
173
|
-
[free + inactive + used, used]
|
174
|
-
else
|
175
|
-
nil
|
176
|
-
end
|
177
|
-
else
|
178
|
-
`top` =~ /(\d+)(K|M) Active, (\d+)(K|M) Inact, (\d+)(K|M) Wired,.*?(\d+)(K|M) Free/
|
179
|
-
if $1 && $2 && $3 && $4 && $5 && $6 && $7 && $8
|
180
|
-
to_kb = lambda do |number, unit|
|
181
|
-
if unit == 'K'
|
182
|
-
number.to_i
|
183
|
-
else
|
184
|
-
number.to_i * 1024
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
active = to_kb.call($1, $2)
|
189
|
-
inactive = to_kb.call($3, $4)
|
190
|
-
wired = to_kb.call($5, $6)
|
191
|
-
free = to_kb.call($7, $8)
|
192
|
-
|
193
|
-
used = active + wired
|
194
|
-
[free + inactive + used, used]
|
195
|
-
else
|
196
|
-
nil
|
197
|
-
end
|
198
|
-
end
|
199
|
-
end
|
200
|
-
end
|
42
|
+
def vm_size_in_mb
|
43
|
+
return sprintf("%.1f MB", vm_size / 1024.0)
|
44
|
+
end
|
201
45
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
end
|
206
|
-
|
207
|
-
# Returns a list of Process objects that match the given search criteria.
|
208
|
-
#
|
209
|
-
# # Search by executable path.
|
210
|
-
# list_processes(:exe => '/usr/sbin/apache2')
|
211
|
-
#
|
212
|
-
# # Search by executable name.
|
213
|
-
# list_processes(:name => 'ruby1.8')
|
214
|
-
#
|
215
|
-
# # Search by process name.
|
216
|
-
# list_processes(:match => 'Passenger FrameworkSpawner')
|
217
|
-
def list_processes(options)
|
218
|
-
if options[:exe]
|
219
|
-
name = options[:exe].sub(/.*\/(.*)/, '\1')
|
220
|
-
if os_name =~ /linux/
|
221
|
-
ps = "ps -C '#{name}'"
|
222
|
-
else
|
223
|
-
ps = "ps -A"
|
224
|
-
options[:match] = Regexp.new(Regexp.escape(name))
|
225
|
-
end
|
226
|
-
elsif options[:name]
|
227
|
-
if os_name =~ /linux/
|
228
|
-
ps = "ps -C '#{options[:name]}'"
|
229
|
-
else
|
230
|
-
ps = "ps -A"
|
231
|
-
options[:match] = Regexp.new(" #{Regexp.escape(options[:name])}")
|
232
|
-
end
|
233
|
-
elsif options[:match]
|
234
|
-
ps = "ps -A"
|
235
|
-
else
|
236
|
-
raise ArgumentError, "Invalid options."
|
237
|
-
end
|
238
|
-
|
239
|
-
processes = []
|
240
|
-
case os_name
|
241
|
-
when /solaris/
|
242
|
-
list = `#{ps} -o pid,ppid,nlwp,vsz,rss,pcpu,comm`.split("\n")
|
243
|
-
threads_known = true
|
244
|
-
when /macosx/
|
245
|
-
list = `#{ps} -w -o pid,ppid,vsz,rss,%cpu,command`.split("\n")
|
246
|
-
threads_known = false
|
247
|
-
else
|
248
|
-
list = `#{ps} -w -o pid,ppid,nlwp,vsz,rss,%cpu,command`.split("\n")
|
249
|
-
threads_known = true
|
250
|
-
end
|
251
|
-
list.shift
|
252
|
-
list.each do |line|
|
253
|
-
line.gsub!(/^ */, '')
|
254
|
-
line.gsub!(/ *$/, '')
|
255
|
-
|
256
|
-
p = Process.new
|
257
|
-
if threads_known
|
258
|
-
p.pid, p.ppid, p.threads, p.vm_size, p.rss, p.cpu, p.name = line.split(/ +/, 7)
|
259
|
-
else
|
260
|
-
p.pid, p.ppid, p.vm_size, p.rss, p.cpu, p.name = line.split(/ +/, 6)
|
261
|
-
end
|
262
|
-
p.name.sub!(/\Aruby: /, '')
|
263
|
-
p.name.sub!(/ \(ruby\)\Z/, '')
|
264
|
-
if p.name !~ /^ps/ && (!options[:match] || p.name.match(options[:match]))
|
265
|
-
# Convert some values to integer.
|
266
|
-
[:pid, :ppid, :vm_size, :rss].each do |attr|
|
267
|
-
p.send("#{attr}=", p.send(attr).to_i)
|
268
|
-
end
|
269
|
-
p.threads = p.threads.to_i if threads_known
|
46
|
+
def rss_in_mb
|
47
|
+
return sprintf("%.1f MB", rss / 1024.0)
|
48
|
+
end
|
270
49
|
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
end
|
279
|
-
|
280
|
-
# Returns the private dirty RSS for the given process, in KB.
|
281
|
-
def determine_private_dirty_rss(pid)
|
282
|
-
total = 0
|
283
|
-
File.read("/proc/#{pid}/smaps").split("\n").each do |line|
|
284
|
-
line =~ /^(Private)_Dirty: +(\d+)/
|
285
|
-
if $2
|
286
|
-
total += $2.to_i
|
287
|
-
end
|
288
|
-
end
|
289
|
-
if total == 0
|
290
|
-
return nil
|
291
|
-
else
|
292
|
-
return total
|
293
|
-
end
|
294
|
-
rescue Errno::EACCES, Errno::ENOENT
|
295
|
-
return nil
|
296
|
-
end
|
297
|
-
end
|
50
|
+
def private_dirty_rss_in_mb
|
51
|
+
if private_dirty_rss.is_a?(Numeric)
|
52
|
+
return sprintf("%.1f MB", private_dirty_rss / 1024.0)
|
53
|
+
else
|
54
|
+
return "?"
|
55
|
+
end
|
56
|
+
end
|
298
57
|
|
299
|
-
|
58
|
+
def to_a
|
59
|
+
return [pid, ppid, vm_size_in_mb, private_dirty_rss_in_mb, rss_in_mb, name]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns a list of Apache processes, which may be the empty list if Apache is
|
64
|
+
# not running. If the Apache executable name is unknown then nil will be returned.
|
65
|
+
def apache_processes
|
66
|
+
@apache_processes ||= begin
|
67
|
+
if PlatformInfo.httpd
|
68
|
+
processes = list_processes(:exe => PlatformInfo.httpd)
|
69
|
+
if processes.empty?
|
70
|
+
# On some Linux distros, the Apache worker processes
|
71
|
+
# are called "httpd.worker"
|
72
|
+
processes = list_processes(:exe => "#{PlatformInfo.httpd}.worker")
|
73
|
+
end
|
74
|
+
processes
|
75
|
+
else
|
76
|
+
nil
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Returns a list of Nginx processes, which may be the empty list if
|
82
|
+
# Nginx is not running.
|
83
|
+
def nginx_processes
|
84
|
+
@nginx_processes ||= list_processes(:exe => "nginx")
|
85
|
+
end
|
86
|
+
|
87
|
+
# Returns a list of Phusion Passenger processes, which may be the empty list if
|
88
|
+
# Phusion Passenger is not running.
|
89
|
+
def passenger_processes
|
90
|
+
@passenger_processes ||= list_processes(:match =>
|
91
|
+
/((^| )Passenger|(^| )Rails:|(^| )Rack:|wsgi-loader.py)/)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Returns the sum of the memory usages of all given processes.
|
95
|
+
# Returns a pair [usage, accurate]. +usage+ is the summed memory usage in KB,
|
96
|
+
# and +accurate+ indicates whether this sum is accurate. This may be false
|
97
|
+
# if some process's memory usage cannot be determined.
|
98
|
+
def sum_memory_usage(processes)
|
99
|
+
total = 0
|
100
|
+
if should_show_private_dirty_rss?
|
101
|
+
accurate = true
|
102
|
+
processes.each do |p|
|
103
|
+
if p.private_dirty_rss.is_a?(Numeric)
|
104
|
+
total += p.private_dirty_rss
|
105
|
+
else
|
106
|
+
accurate = true
|
107
|
+
end
|
108
|
+
end
|
109
|
+
return [total, accurate]
|
110
|
+
else
|
111
|
+
processes.each do |p|
|
112
|
+
total += p.rss
|
113
|
+
end
|
114
|
+
return [total, true]
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def platform_provides_private_dirty_rss_information?
|
119
|
+
return os_name == "linux"
|
120
|
+
end
|
121
|
+
|
122
|
+
# Returns whether root privileges are required in order to measure private dirty RSS.
|
123
|
+
# Only meaningful if #platform_provides_private_dirty_rss_information? returns true.
|
124
|
+
def root_privileges_required_for_private_dirty_rss?
|
125
|
+
all_processes = (apache_processes || []) + nginx_processes + passenger_processes
|
126
|
+
return all_processes.any?{ |p| p.private_dirty_rss.nil? }
|
127
|
+
end
|
128
|
+
|
129
|
+
def should_show_private_dirty_rss?
|
130
|
+
return platform_provides_private_dirty_rss_information? &&
|
131
|
+
(::Process.euid == 0 || root_privileges_required_for_private_dirty_rss?)
|
132
|
+
end
|
133
|
+
|
134
|
+
# Determine the system's RAM usage, not including swap.
|
135
|
+
# Returns a tuple [total, used] where both numbers are in KB, or nil
|
136
|
+
# if the system's RAM usage cannot be determined.
|
137
|
+
def system_ram_usage
|
138
|
+
@total_system_ram ||= begin
|
139
|
+
case os_name
|
140
|
+
when /linux/
|
141
|
+
free_text = `free -k`
|
142
|
+
|
143
|
+
free_text =~ %r{Mem:(.+)$}
|
144
|
+
line = $1.strip
|
145
|
+
total = line.split(/ +/).first.to_i
|
146
|
+
|
147
|
+
free_text =~ %r{buffers/cache:(.+)$}
|
148
|
+
line = $1.strip
|
149
|
+
used = line.split(/ +/).first.to_i
|
150
|
+
|
151
|
+
[total, used]
|
152
|
+
when /macosx/
|
153
|
+
vm_stat = `vm_stat`
|
154
|
+
vm_stat =~ /page size of (\d+) bytes/
|
155
|
+
page_size = $1
|
156
|
+
vm_stat =~ /Pages free: +(\d+)/
|
157
|
+
free = $1
|
158
|
+
vm_stat =~ /Pages active: +(\d+)/
|
159
|
+
active = $1
|
160
|
+
vm_stat =~ /Pages inactive: +(\d+)/
|
161
|
+
inactive = $1
|
162
|
+
vm_stat =~ /Pages wired down: +(\d+)/
|
163
|
+
wired = $1
|
164
|
+
|
165
|
+
if page_size && free && active && inactive && wired
|
166
|
+
page_size = page_size.to_i
|
167
|
+
free = free.to_i * page_size / 1024
|
168
|
+
active = active.to_i * page_size / 1024
|
169
|
+
inactive = inactive.to_i * page_size / 1024
|
170
|
+
wired = wired.to_i * page_size / 1024
|
171
|
+
|
172
|
+
used = active + wired
|
173
|
+
[free + inactive + used, used]
|
174
|
+
else
|
175
|
+
nil
|
176
|
+
end
|
177
|
+
else
|
178
|
+
`top` =~ /(\d+)(K|M) Active, (\d+)(K|M) Inact, (\d+)(K|M) Wired,.*?(\d+)(K|M) Free/
|
179
|
+
if $1 && $2 && $3 && $4 && $5 && $6 && $7 && $8
|
180
|
+
to_kb = lambda do |number, unit|
|
181
|
+
if unit == 'K'
|
182
|
+
number.to_i
|
183
|
+
else
|
184
|
+
number.to_i * 1024
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
active = to_kb.call($1, $2)
|
189
|
+
inactive = to_kb.call($3, $4)
|
190
|
+
wired = to_kb.call($5, $6)
|
191
|
+
free = to_kb.call($7, $8)
|
192
|
+
|
193
|
+
used = active + wired
|
194
|
+
[free + inactive + used, used]
|
195
|
+
else
|
196
|
+
nil
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
private
|
203
|
+
def os_name
|
204
|
+
return PlatformInfo.os_name
|
205
|
+
end
|
206
|
+
|
207
|
+
# Returns a list of Process objects that match the given search criteria.
|
208
|
+
#
|
209
|
+
# # Search by executable path.
|
210
|
+
# list_processes(:exe => '/usr/sbin/apache2')
|
211
|
+
#
|
212
|
+
# # Search by executable name.
|
213
|
+
# list_processes(:name => 'ruby1.8')
|
214
|
+
#
|
215
|
+
# # Search by process name.
|
216
|
+
# list_processes(:match => 'Passenger FrameworkSpawner')
|
217
|
+
def list_processes(options)
|
218
|
+
if options[:exe]
|
219
|
+
name = options[:exe].sub(/.*\/(.*)/, '\1')
|
220
|
+
if os_name =~ /linux/
|
221
|
+
ps = "ps -C '#{name}'"
|
222
|
+
else
|
223
|
+
ps = "ps -A"
|
224
|
+
options[:match] = Regexp.new(Regexp.escape(name))
|
225
|
+
end
|
226
|
+
elsif options[:name]
|
227
|
+
if os_name =~ /linux/
|
228
|
+
ps = "ps -C '#{options[:name]}'"
|
229
|
+
else
|
230
|
+
ps = "ps -A"
|
231
|
+
options[:match] = Regexp.new(" #{Regexp.escape(options[:name])}")
|
232
|
+
end
|
233
|
+
elsif options[:match]
|
234
|
+
ps = "ps -A"
|
235
|
+
else
|
236
|
+
raise ArgumentError, "Invalid options."
|
237
|
+
end
|
238
|
+
|
239
|
+
processes = []
|
240
|
+
case os_name
|
241
|
+
when /solaris/
|
242
|
+
list = `#{ps} -o pid,ppid,nlwp,vsz,rss,pcpu,comm`.split("\n")
|
243
|
+
threads_known = true
|
244
|
+
when /macosx/
|
245
|
+
list = `#{ps} -w -o pid,ppid,vsz,rss,%cpu,command`.split("\n")
|
246
|
+
threads_known = false
|
247
|
+
else
|
248
|
+
list = `#{ps} -w -o pid,ppid,nlwp,vsz,rss,%cpu,command`.split("\n")
|
249
|
+
threads_known = true
|
250
|
+
end
|
251
|
+
list.shift
|
252
|
+
list.each do |line|
|
253
|
+
line.gsub!(/^ */, '')
|
254
|
+
line.gsub!(/ *$/, '')
|
255
|
+
|
256
|
+
p = Process.new
|
257
|
+
if threads_known
|
258
|
+
p.pid, p.ppid, p.threads, p.vm_size, p.rss, p.cpu, p.name = line.split(/ +/, 7)
|
259
|
+
else
|
260
|
+
p.pid, p.ppid, p.vm_size, p.rss, p.cpu, p.name = line.split(/ +/, 6)
|
261
|
+
end
|
262
|
+
p.name.sub!(/\Aruby: /, '')
|
263
|
+
p.name.sub!(/ \(ruby\)\Z/, '')
|
264
|
+
if p.name !~ /^ps/ && (!options[:match] || p.name.match(options[:match]))
|
265
|
+
# Convert some values to integer.
|
266
|
+
[:pid, :ppid, :vm_size, :rss].each do |attr|
|
267
|
+
p.send("#{attr}=", p.send(attr).to_i)
|
268
|
+
end
|
269
|
+
p.threads = p.threads.to_i if threads_known
|
270
|
+
|
271
|
+
if platform_provides_private_dirty_rss_information?
|
272
|
+
p.private_dirty_rss = determine_private_dirty_rss(p.pid)
|
273
|
+
end
|
274
|
+
processes << p
|
275
|
+
end
|
276
|
+
end
|
277
|
+
return processes
|
278
|
+
end
|
279
|
+
|
280
|
+
# Returns the private dirty RSS for the given process, in KB.
|
281
|
+
def determine_private_dirty_rss(pid)
|
282
|
+
total = 0
|
283
|
+
File.read("/proc/#{pid}/smaps").split("\n").each do |line|
|
284
|
+
line =~ /^(Private)_Dirty: +(\d+)/
|
285
|
+
if $2
|
286
|
+
total += $2.to_i
|
287
|
+
end
|
288
|
+
end
|
289
|
+
if total == 0
|
290
|
+
return nil
|
291
|
+
else
|
292
|
+
return total
|
293
|
+
end
|
294
|
+
rescue Errno::EACCES, Errno::ENOENT
|
295
|
+
return nil
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
end # module AdminTools
|
300
300
|
end # module PhusionPassenger
|