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.

Files changed (218) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.asc +7 -7
  3. data.tar.gz.asc +7 -7
  4. data/.editorconfig +11 -5
  5. data/CHANGELOG +38 -0
  6. data/CONTRIBUTING.md +1 -4
  7. data/Gemfile +0 -1
  8. data/Gemfile.lock +0 -2
  9. data/Rakefile +33 -33
  10. data/bin/passenger +1 -1
  11. data/bin/passenger-config +1 -1
  12. data/bin/passenger-install-apache2-module +800 -800
  13. data/bin/passenger-install-nginx-module +592 -592
  14. data/bin/passenger-memory-stats +127 -127
  15. data/bin/passenger-status +216 -216
  16. data/build/agents.rb +127 -127
  17. data/build/apache2.rb +87 -87
  18. data/build/basics.rb +60 -60
  19. data/build/common_library.rb +165 -165
  20. data/build/cplusplus_support.rb +51 -51
  21. data/build/cxx_tests.rb +268 -268
  22. data/build/debian.rb +143 -143
  23. data/build/documentation.rb +58 -58
  24. data/build/integration_tests.rb +81 -81
  25. data/build/misc.rb +132 -132
  26. data/build/nginx.rb +20 -20
  27. data/build/node_tests.rb +7 -7
  28. data/build/oxt_tests.rb +14 -14
  29. data/build/packaging.rb +570 -570
  30. data/build/preprocessor.rb +260 -260
  31. data/build/rake_extensions.rb +71 -71
  32. data/build/ruby_extension.rb +29 -29
  33. data/build/ruby_tests.rb +6 -6
  34. data/build/test_basics.rb +37 -37
  35. data/debian.template/control.template +3 -5
  36. data/dev/copy_boost_headers +134 -134
  37. data/dev/install_scripts_bootstrap_code.rb +25 -25
  38. data/dev/list_tests +20 -20
  39. data/dev/ruby_server.rb +223 -223
  40. data/dev/runner +18 -18
  41. data/doc/ServerOptimizationGuide.txt.md +55 -2
  42. data/doc/Users guide Nginx.txt +0 -26
  43. data/doc/Users guide Standalone.txt +5 -1
  44. data/doc/users_guide_snippets/tips.txt +9 -0
  45. data/ext/common/ApplicationPool2/Group.h +23 -11
  46. data/ext/common/ApplicationPool2/Implementation.cpp +32 -7
  47. data/ext/common/ApplicationPool2/Pool.h +22 -17
  48. data/ext/common/ApplicationPool2/SmartSpawner.h +4 -1
  49. data/ext/common/ApplicationPool2/Spawner.h +1 -1
  50. data/ext/common/Constants.h +1 -1
  51. data/ext/common/agents/Base.cpp +35 -20
  52. data/ext/common/agents/HelperAgent/Main.cpp +8 -1
  53. data/ext/common/agents/HelperAgent/OptionParser.h +18 -4
  54. data/ext/common/agents/HelperAgent/RequestHandler.h +2 -83
  55. data/ext/common/agents/HelperAgent/RequestHandler/ForwardResponse.cpp +54 -1
  56. data/ext/common/agents/HelperAgent/RequestHandler/InitRequest.cpp +7 -4
  57. data/ext/common/agents/Main.cpp +1 -1
  58. data/ext/common/agents/Watchdog/Main.cpp +54 -19
  59. data/ext/nginx/Configuration.c +7 -0
  60. data/ext/nginx/ContentHandler.c +9 -1
  61. data/helper-scripts/backtrace-sanitizer.rb +106 -87
  62. data/helper-scripts/crash-watch.rb +32 -0
  63. data/helper-scripts/download_binaries/extconf.rb +38 -38
  64. data/helper-scripts/meteor-loader.rb +107 -107
  65. data/helper-scripts/prespawn +101 -101
  66. data/helper-scripts/rack-loader.rb +96 -96
  67. data/helper-scripts/rack-preloader.rb +137 -137
  68. data/lib/phusion_passenger.rb +292 -292
  69. data/lib/phusion_passenger/abstract_installer.rb +438 -438
  70. data/lib/phusion_passenger/active_support3_extensions/init.rb +168 -170
  71. data/lib/phusion_passenger/admin_tools.rb +20 -20
  72. data/lib/phusion_passenger/admin_tools/instance.rb +178 -178
  73. data/lib/phusion_passenger/admin_tools/instance_registry.rb +61 -61
  74. data/lib/phusion_passenger/admin_tools/memory_stats.rb +267 -267
  75. data/lib/phusion_passenger/apache2/config_options.rb +182 -182
  76. data/lib/phusion_passenger/common_library.rb +479 -485
  77. data/lib/phusion_passenger/config/about_command.rb +161 -161
  78. data/lib/phusion_passenger/config/admin_command_command.rb +129 -129
  79. data/lib/phusion_passenger/config/agent_compiler.rb +121 -121
  80. data/lib/phusion_passenger/config/build_native_support_command.rb +43 -43
  81. data/lib/phusion_passenger/config/command.rb +25 -25
  82. data/lib/phusion_passenger/config/compile_agent_command.rb +62 -62
  83. data/lib/phusion_passenger/config/compile_nginx_engine_command.rb +88 -73
  84. data/lib/phusion_passenger/config/detach_process_command.rb +72 -72
  85. data/lib/phusion_passenger/config/download_agent_command.rb +246 -227
  86. data/lib/phusion_passenger/config/download_nginx_engine_command.rb +245 -224
  87. data/lib/phusion_passenger/config/install_agent_command.rb +144 -132
  88. data/lib/phusion_passenger/config/install_standalone_runtime_command.rb +205 -185
  89. data/lib/phusion_passenger/config/installation_utils.rb +204 -204
  90. data/lib/phusion_passenger/config/list_instances_command.rb +64 -64
  91. data/lib/phusion_passenger/config/main.rb +152 -152
  92. data/lib/phusion_passenger/config/nginx_engine_compiler.rb +319 -300
  93. data/lib/phusion_passenger/config/reopen_logs_command.rb +67 -67
  94. data/lib/phusion_passenger/config/restart_app_command.rb +155 -155
  95. data/lib/phusion_passenger/config/system_metrics_command.rb +13 -13
  96. data/lib/phusion_passenger/config/utils.rb +95 -95
  97. data/lib/phusion_passenger/config/validate_install_command.rb +198 -198
  98. data/lib/phusion_passenger/console_text_template.rb +25 -25
  99. data/lib/phusion_passenger/constants.rb +90 -90
  100. data/lib/phusion_passenger/debug_logging.rb +106 -106
  101. data/lib/phusion_passenger/loader_shared_helpers.rb +447 -432
  102. data/lib/phusion_passenger/message_channel.rb +312 -312
  103. data/lib/phusion_passenger/message_client.rb +176 -176
  104. data/lib/phusion_passenger/native_support.rb +369 -369
  105. data/lib/phusion_passenger/nginx/config_options.rb +297 -297
  106. data/lib/phusion_passenger/packaging.rb +131 -131
  107. data/lib/phusion_passenger/platform_info.rb +360 -360
  108. data/lib/phusion_passenger/platform_info/apache.rb +767 -767
  109. data/lib/phusion_passenger/platform_info/apache_detector.rb +199 -199
  110. data/lib/phusion_passenger/platform_info/binary_compatibility.rb +107 -107
  111. data/lib/phusion_passenger/platform_info/compiler.rb +570 -570
  112. data/lib/phusion_passenger/platform_info/curl.rb +32 -32
  113. data/lib/phusion_passenger/platform_info/cxx_portability.rb +188 -188
  114. data/lib/phusion_passenger/platform_info/depcheck.rb +372 -372
  115. data/lib/phusion_passenger/platform_info/depcheck_specs/apache2.rb +109 -109
  116. data/lib/phusion_passenger/platform_info/depcheck_specs/compiler_toolchain.rb +4 -4
  117. data/lib/phusion_passenger/platform_info/depcheck_specs/gems.rb +10 -34
  118. data/lib/phusion_passenger/platform_info/depcheck_specs/libs.rb +101 -101
  119. data/lib/phusion_passenger/platform_info/depcheck_specs/ruby.rb +5 -5
  120. data/lib/phusion_passenger/platform_info/depcheck_specs/utilities.rb +13 -13
  121. data/lib/phusion_passenger/platform_info/linux.rb +55 -55
  122. data/lib/phusion_passenger/platform_info/operating_system.rb +149 -149
  123. data/lib/phusion_passenger/platform_info/ruby.rb +468 -448
  124. data/lib/phusion_passenger/platform_info/zlib.rb +9 -9
  125. data/lib/phusion_passenger/plugin.rb +66 -66
  126. data/lib/phusion_passenger/preloader_shared_helpers.rb +126 -126
  127. data/lib/phusion_passenger/public_api.rb +191 -191
  128. data/lib/phusion_passenger/rack/out_of_band_gc.rb +93 -94
  129. data/lib/phusion_passenger/rack/thread_handler_extension.rb +231 -227
  130. data/lib/phusion_passenger/request_handler.rb +567 -577
  131. data/lib/phusion_passenger/request_handler/thread_handler.rb +379 -381
  132. data/lib/phusion_passenger/ruby_core_enhancements.rb +86 -86
  133. data/lib/phusion_passenger/ruby_core_io_enhancements.rb +74 -74
  134. data/lib/phusion_passenger/simple_benchmarking.rb +25 -25
  135. data/lib/phusion_passenger/standalone/app_finder.rb +153 -150
  136. data/lib/phusion_passenger/standalone/command.rb +44 -40
  137. data/lib/phusion_passenger/standalone/config_utils.rb +53 -53
  138. data/lib/phusion_passenger/standalone/control_utils.rb +38 -59
  139. data/lib/phusion_passenger/standalone/main.rb +73 -73
  140. data/lib/phusion_passenger/standalone/start_command.rb +697 -685
  141. data/lib/phusion_passenger/standalone/start_command/builtin_engine.rb +193 -155
  142. data/lib/phusion_passenger/standalone/start_command/nginx_engine.rb +162 -133
  143. data/lib/phusion_passenger/standalone/status_command.rb +64 -64
  144. data/lib/phusion_passenger/standalone/stop_command.rb +72 -72
  145. data/lib/phusion_passenger/standalone/version_command.rb +9 -9
  146. data/lib/phusion_passenger/union_station/connection.rb +32 -32
  147. data/lib/phusion_passenger/union_station/core.rb +251 -251
  148. data/lib/phusion_passenger/union_station/transaction.rb +126 -126
  149. data/lib/phusion_passenger/utils.rb +199 -167
  150. data/lib/phusion_passenger/utils/ansi_colors.rb +128 -128
  151. data/lib/phusion_passenger/utils/download.rb +196 -196
  152. data/lib/phusion_passenger/utils/file_system_watcher.rb +158 -158
  153. data/lib/phusion_passenger/utils/hosts_file_parser.rb +101 -101
  154. data/lib/phusion_passenger/utils/lock.rb +31 -31
  155. data/lib/phusion_passenger/utils/native_support_utils.rb +31 -31
  156. data/lib/phusion_passenger/utils/progress_bar.rb +26 -26
  157. data/lib/phusion_passenger/utils/shellwords.rb +20 -20
  158. data/lib/phusion_passenger/utils/terminal_choice_menu.rb +206 -206
  159. data/lib/phusion_passenger/utils/unseekable_socket.rb +272 -272
  160. data/lib/phusion_passenger/vendor/crash_watch/app.rb +129 -0
  161. data/lib/phusion_passenger/vendor/crash_watch/gdb_controller.rb +341 -0
  162. data/lib/phusion_passenger/vendor/crash_watch/version.rb +24 -0
  163. data/lib/phusion_passenger/vendor/daemon_controller.rb +877 -0
  164. data/lib/phusion_passenger/vendor/daemon_controller/lock_file.rb +127 -0
  165. data/lib/phusion_passenger/vendor/daemon_controller/spawn.rb +26 -0
  166. data/lib/phusion_passenger/vendor/daemon_controller/version.rb +29 -0
  167. data/packaging/rpm/passenger_spec/passenger.spec.template +0 -1
  168. data/passenger.gemspec +0 -1
  169. data/resources/templates/config/nginx_engine_compiler/possible_solutions_for_download_and_extraction_problems.txt.erb +27 -0
  170. data/resources/templates/standalone/config.erb +19 -15
  171. data/test/integration_tests/apache2_tests.rb +566 -566
  172. data/test/integration_tests/downloaded_binaries_tests.rb +126 -125
  173. data/test/integration_tests/native_packaging_spec.rb +296 -296
  174. data/test/integration_tests/nginx_tests.rb +393 -393
  175. data/test/integration_tests/shared/example_webapp_tests.rb +282 -280
  176. data/test/integration_tests/source_packaging_test.rb +138 -138
  177. data/test/integration_tests/spec_helper.rb +5 -5
  178. data/test/integration_tests/standalone_tests.rb +367 -367
  179. data/test/ruby/debug_logging_spec.rb +133 -133
  180. data/test/ruby/message_channel_spec.rb +186 -186
  181. data/test/ruby/rack/loader_spec.rb +28 -28
  182. data/test/ruby/rack/preloader_spec.rb +34 -34
  183. data/test/ruby/rails3.0/loader_spec.rb +12 -12
  184. data/test/ruby/rails3.0/preloader_spec.rb +18 -18
  185. data/test/ruby/rails3.1/loader_spec.rb +12 -12
  186. data/test/ruby/rails3.1/preloader_spec.rb +18 -18
  187. data/test/ruby/rails3.2/loader_spec.rb +12 -12
  188. data/test/ruby/rails3.2/preloader_spec.rb +18 -18
  189. data/test/ruby/rails4.0/loader_spec.rb +12 -12
  190. data/test/ruby/rails4.0/preloader_spec.rb +18 -18
  191. data/test/ruby/rails4.1/loader_spec.rb +12 -12
  192. data/test/ruby/rails4.1/preloader_spec.rb +18 -18
  193. data/test/ruby/request_handler_spec.rb +730 -730
  194. data/test/ruby/shared/loader_sharedspec.rb +224 -224
  195. data/test/ruby/shared/rails/union_station_extensions_sharedspec.rb +327 -327
  196. data/test/ruby/shared/ruby_loader_sharedspec.rb +47 -47
  197. data/test/ruby/spec_helper.rb +65 -65
  198. data/test/ruby/standalone/runtime_installer_spec.rb +384 -384
  199. data/test/ruby/union_station_spec.rb +276 -276
  200. data/test/ruby/utils/file_system_watcher_spec.rb +220 -220
  201. data/test/ruby/utils/hosts_file_parser.rb +248 -248
  202. data/test/ruby/utils/tee_input_spec.rb +215 -215
  203. data/test/ruby/utils/unseekable_socket_spec.rb +57 -57
  204. data/test/ruby/utils_spec.rb +21 -21
  205. data/test/stub/rack/config.ru +87 -87
  206. data/test/stub/rack/library.rb +8 -8
  207. data/test/stub/rack/start.rb +30 -30
  208. data/test/support/apache2_controller.rb +191 -191
  209. data/test/support/nginx_controller.rb +90 -99
  210. data/test/support/placebo-preloader.rb +57 -57
  211. data/test/support/test_helper.rb +435 -435
  212. metadata +11 -21
  213. metadata.gz.asc +7 -7
  214. data/lib/phusion_passenger/standalone/command2.rb +0 -292
  215. data/lib/phusion_passenger/standalone/start2_command.rb +0 -799
  216. data/resources/templates/standalone/download_tool_missing.txt.erb +0 -18
  217. data/resources/templates/standalone/possible_solutions_for_download_and_extraction_problems.txt.erb +0 -17
  218. data/resources/templates/standalone/run_installer_as_root.txt.erb +0 -8
@@ -26,7 +26,7 @@
26
26
  source_root = File.expand_path("..", File.dirname(__FILE__))
27
27
  $LOAD_PATH.unshift("#{source_root}/lib")
28
28
  begin
29
- require 'rubygems'
29
+ require 'rubygems'
30
30
  rescue LoadError
31
31
  end
32
32
  require 'phusion_passenger'
@@ -42,136 +42,136 @@ include PhusionPassenger
42
42
 
43
43
  # Container for tabular data.
44
44
  class Table
45
- def initialize(column_names, colors)
46
- @column_names = column_names
47
- @rows = []
48
- @colors = colors
49
- end
50
-
51
- def add_row(values)
52
- @rows << values.to_a
53
- end
54
-
55
- def add_rows(list_of_rows)
56
- list_of_rows.each do |row|
57
- add_row(row)
58
- end
59
- end
60
-
61
- def remove_column(name)
62
- i = @column_names.index(name)
63
- @column_names.delete_at(i)
64
- @rows.each do |row|
65
- row.delete_at(i)
66
- end
67
- end
68
-
69
- def to_s(title = nil)
70
- max_column_widths = [1] * @column_names.size
71
- (@rows + [@column_names]).each do |row|
72
- row.each_with_index do |value, i|
73
- max_column_widths[i] = [value.to_s.size, max_column_widths[i]].max
74
- end
75
- end
76
-
77
- format_string = max_column_widths.map{ |i| "%#{-i}s" }.join(" ")
78
- header = sprintf(format_string, *@column_names).rstrip << "\n"
79
- if title
80
- free_space = header.size - title.size - 2
81
- if free_space <= 0
82
- left_bar_size = 3
83
- right_bar_size = 3
84
- else
85
- left_bar_size = free_space / 2
86
- right_bar_size = free_space - left_bar_size
87
- end
88
- result = "#{@colors.blue_bg}#{@colors.bold}#{@colors.yellow}\n"
89
- result << "#{"-" * left_bar_size} #{title} #{"-" * right_bar_size}\n"
90
- if !@rows.empty?
91
- result << @colors.white
92
- result << header
93
- end
94
- else
95
- result = header.dup
96
- end
97
- if @rows.empty?
98
- result << @colors.reset
99
- else
100
- result << ("-" * header.size) << "#{@colors.reset}\n"
101
- @rows.each do |row|
102
- result << sprintf(format_string, *row).rstrip << "\n"
103
- end
104
- end
105
- result
106
- end
45
+ def initialize(column_names, colors)
46
+ @column_names = column_names
47
+ @rows = []
48
+ @colors = colors
49
+ end
50
+
51
+ def add_row(values)
52
+ @rows << values.to_a
53
+ end
54
+
55
+ def add_rows(list_of_rows)
56
+ list_of_rows.each do |row|
57
+ add_row(row)
58
+ end
59
+ end
60
+
61
+ def remove_column(name)
62
+ i = @column_names.index(name)
63
+ @column_names.delete_at(i)
64
+ @rows.each do |row|
65
+ row.delete_at(i)
66
+ end
67
+ end
68
+
69
+ def to_s(title = nil)
70
+ max_column_widths = [1] * @column_names.size
71
+ (@rows + [@column_names]).each do |row|
72
+ row.each_with_index do |value, i|
73
+ max_column_widths[i] = [value.to_s.size, max_column_widths[i]].max
74
+ end
75
+ end
76
+
77
+ format_string = max_column_widths.map{ |i| "%#{-i}s" }.join(" ")
78
+ header = sprintf(format_string, *@column_names).rstrip << "\n"
79
+ if title
80
+ free_space = header.size - title.size - 2
81
+ if free_space <= 0
82
+ left_bar_size = 3
83
+ right_bar_size = 3
84
+ else
85
+ left_bar_size = free_space / 2
86
+ right_bar_size = free_space - left_bar_size
87
+ end
88
+ result = "#{@colors.blue_bg}#{@colors.bold}#{@colors.yellow}\n"
89
+ result << "#{"-" * left_bar_size} #{title} #{"-" * right_bar_size}\n"
90
+ if !@rows.empty?
91
+ result << @colors.white
92
+ result << header
93
+ end
94
+ else
95
+ result = header.dup
96
+ end
97
+ if @rows.empty?
98
+ result << @colors.reset
99
+ else
100
+ result << ("-" * header.size) << "#{@colors.reset}\n"
101
+ @rows.each do |row|
102
+ result << sprintf(format_string, *row).rstrip << "\n"
103
+ end
104
+ end
105
+ result
106
+ end
107
107
  end
108
108
 
109
109
  class App
110
- def initialize
111
- @stats = AdminTools::MemoryStats.new
112
- @colors = Utils::AnsiColors.new
113
- end
114
-
115
- def start
116
- puts "Version: #{PhusionPassenger::VERSION_STRING}"
117
- puts "Date : #{Time.now}"
118
- if @stats.apache_processes
119
- print_process_list("Apache processes", @stats.apache_processes)
120
- else
121
- puts "#{@colors.blue_bg}#{@colors.bold}#{@colors.yellow}------------- Apache processes -------------#{@colors.reset}\n"
122
- STDERR.puts "*** WARNING: The Apache executable cannot be found."
123
- STDERR.puts "Please set the APXS2 environment variable to your 'apxs2' " <<
124
- "executable's filename, or set the HTTPD environment variable " <<
125
- "to your 'httpd' or 'apache2' executable's filename."
126
- end
127
-
128
- puts
129
- print_process_list("Nginx processes", @stats.nginx_processes)
130
-
131
- puts
132
- print_process_list("Passenger processes", @stats.passenger_processes, :show_ppid => false)
133
-
134
- if @stats.platform_provides_private_dirty_rss_information? &&
135
- Process.euid != 0 &&
136
- @stats.root_privileges_required_for_private_dirty_rss?
137
- puts "*** WARNING: Please run this tool with #{@colors.bold}#{PlatformInfo.ruby_sudo_command}#{@colors.reset}. Otherwise the " <<
138
- "private dirty RSS (a reliable metric for real memory usage) of processes cannot be determined."
139
- end
140
- end
141
-
110
+ def initialize
111
+ @stats = AdminTools::MemoryStats.new
112
+ @colors = Utils::AnsiColors.new
113
+ end
114
+
115
+ def start
116
+ puts "Version: #{PhusionPassenger::VERSION_STRING}"
117
+ puts "Date : #{Time.now}"
118
+ if @stats.apache_processes
119
+ print_process_list("Apache processes", @stats.apache_processes)
120
+ else
121
+ puts "#{@colors.blue_bg}#{@colors.bold}#{@colors.yellow}------------- Apache processes -------------#{@colors.reset}\n"
122
+ STDERR.puts "*** WARNING: The Apache executable cannot be found."
123
+ STDERR.puts "Please set the APXS2 environment variable to your 'apxs2' " <<
124
+ "executable's filename, or set the HTTPD environment variable " <<
125
+ "to your 'httpd' or 'apache2' executable's filename."
126
+ end
127
+
128
+ puts
129
+ print_process_list("Nginx processes", @stats.nginx_processes)
130
+
131
+ puts
132
+ print_process_list("Passenger processes", @stats.passenger_processes, :show_ppid => false)
133
+
134
+ if @stats.platform_provides_private_dirty_rss_information? &&
135
+ Process.euid != 0 &&
136
+ @stats.root_privileges_required_for_private_dirty_rss?
137
+ puts "*** WARNING: Please run this tool with #{@colors.bold}#{PlatformInfo.ruby_sudo_command}#{@colors.reset}. Otherwise the " <<
138
+ "private dirty RSS (a reliable metric for real memory usage) of processes cannot be determined."
139
+ end
140
+ end
141
+
142
142
  private
143
- def print_process_list(title, processes, options = {})
144
- table = Table.new(%w{PID PPID VMSize Private Resident Name}, @colors)
145
- table.add_rows(processes)
146
- if options.has_key?(:show_ppid) && !options[:show_ppid]
147
- table.remove_column('PPID')
148
- end
149
- if @stats.platform_provides_private_dirty_rss_information?
150
- table.remove_column('Resident')
151
- else
152
- table.remove_column('Private')
153
- end
154
- puts table.to_s(title)
155
-
156
- if @stats.platform_provides_private_dirty_rss_information?
157
- total_private_dirty_rss = 0
158
- some_private_dirty_rss_cannot_be_determined = false
159
- processes.each do |p|
160
- if p.private_dirty_rss.is_a?(Numeric)
161
- total_private_dirty_rss += p.private_dirty_rss
162
- else
163
- some_private_dirty_rss_cannot_be_determined = true
164
- end
165
- end
166
- puts "### Processes: #{processes.size}"
167
- printf "### Total private dirty RSS: %.2f MB", total_private_dirty_rss / 1024.0
168
- if some_private_dirty_rss_cannot_be_determined
169
- puts " (?)"
170
- else
171
- puts
172
- end
173
- end
174
- end
143
+ def print_process_list(title, processes, options = {})
144
+ table = Table.new(%w{PID PPID VMSize Private Resident Name}, @colors)
145
+ table.add_rows(processes)
146
+ if options.has_key?(:show_ppid) && !options[:show_ppid]
147
+ table.remove_column('PPID')
148
+ end
149
+ if @stats.platform_provides_private_dirty_rss_information?
150
+ table.remove_column('Resident')
151
+ else
152
+ table.remove_column('Private')
153
+ end
154
+ puts table.to_s(title)
155
+
156
+ if @stats.platform_provides_private_dirty_rss_information?
157
+ total_private_dirty_rss = 0
158
+ some_private_dirty_rss_cannot_be_determined = false
159
+ processes.each do |p|
160
+ if p.private_dirty_rss.is_a?(Numeric)
161
+ total_private_dirty_rss += p.private_dirty_rss
162
+ else
163
+ some_private_dirty_rss_cannot_be_determined = true
164
+ end
165
+ end
166
+ puts "### Processes: #{processes.size}"
167
+ printf "### Total private dirty RSS: %.2f MB", total_private_dirty_rss / 1024.0
168
+ if some_private_dirty_rss_cannot_be_determined
169
+ puts " (?)"
170
+ else
171
+ puts
172
+ end
173
+ end
174
+ end
175
175
  end
176
176
 
177
177
  App.new.start
data/bin/passenger-status CHANGED
@@ -26,7 +26,7 @@
26
26
  source_root = File.expand_path("..", File.dirname(__FILE__))
27
27
  $LOAD_PATH.unshift("#{source_root}/lib")
28
28
  begin
29
- require 'rubygems'
29
+ require 'rubygems'
30
30
  rescue LoadError
31
31
  end
32
32
  require 'phusion_passenger'
@@ -51,263 +51,263 @@ DEFAULT_OPTIONS = { :show => 'pool', :color => STDOUT.tty?, :header => true }.fr
51
51
  ##### Show status command #####
52
52
 
53
53
  def command_show_status(argv, options)
54
- if argv.empty?
55
- instance = find_sole_instance
56
- else
57
- instance = find_instance_by_name_prefix(argv[0])
58
- end
59
- show_status(instance, options)
54
+ if argv.empty?
55
+ instance = find_sole_instance
56
+ else
57
+ instance = find_instance_by_name_prefix(argv[0])
58
+ end
59
+ show_status(instance, options)
60
60
  end
61
61
 
62
62
  def find_sole_instance
63
- instances = InstanceRegistry.new.list
64
- if instances.empty?
65
- abort "ERROR: #{PROGRAM_NAME} doesn't seem to be running. If you " +
66
- "are sure that it is running, then the causes of this problem could be:\n\n" +
67
- "1. You customized the instance registry directory using Apache's " +
68
- "PassengerInstanceRegistryDir option, Nginx's passenger_instance_registry_dir " +
69
- "option, or #{PROGRAM_NAME} Standalone's --instance-registry-dir command line " +
70
- "argument. If so, please set the environment variable PASSENGER_INSTANCE_REGISTRY_DIR " +
71
- "to that directory and run passenger-status again.\n" +
72
- "2. The instance directory has been removed by an operating system background service. " +
73
- "Please set a different instance registry directory using Apache's " +
74
- "PassengerInstanceRegistryDir option, Nginx's passenger_instance_registry_dir " +
75
- "option, or #{PROGRAM_NAME} Standalone's --instance-registry-dir command line " +
76
- "argument."
77
- elsif instances.size == 1
78
- return instances.first
79
- else
80
- puts "It appears that multiple #{PROGRAM_NAME} instances are running. Please"
81
- puts "select a specific one by running:"
82
- puts
83
- puts " passenger-status <NAME>"
84
- puts
85
- puts "The following instances are running:"
86
- puts
87
- printf "%-25s %s\n", "Name", "Description"
88
- puts "------------------------------------------------------------------"
89
- instances.each do |instance|
90
- printf "%-25s %s\n", instance.name, instance.server_software
91
- end
92
- exit 1
93
- end
63
+ instances = InstanceRegistry.new.list
64
+ if instances.empty?
65
+ abort "ERROR: #{PROGRAM_NAME} doesn't seem to be running. If you " +
66
+ "are sure that it is running, then the causes of this problem could be:\n\n" +
67
+ "1. You customized the instance registry directory using Apache's " +
68
+ "PassengerInstanceRegistryDir option, Nginx's passenger_instance_registry_dir " +
69
+ "option, or #{PROGRAM_NAME} Standalone's --instance-registry-dir command line " +
70
+ "argument. If so, please set the environment variable PASSENGER_INSTANCE_REGISTRY_DIR " +
71
+ "to that directory and run passenger-status again.\n" +
72
+ "2. The instance directory has been removed by an operating system background service. " +
73
+ "Please set a different instance registry directory using Apache's " +
74
+ "PassengerInstanceRegistryDir option, Nginx's passenger_instance_registry_dir " +
75
+ "option, or #{PROGRAM_NAME} Standalone's --instance-registry-dir command line " +
76
+ "argument."
77
+ elsif instances.size == 1
78
+ return instances.first
79
+ else
80
+ puts "It appears that multiple #{PROGRAM_NAME} instances are running. Please"
81
+ puts "select a specific one by running:"
82
+ puts
83
+ puts " passenger-status <NAME>"
84
+ puts
85
+ puts "The following instances are running:"
86
+ puts
87
+ printf "%-25s %s\n", "Name", "Description"
88
+ puts "------------------------------------------------------------------"
89
+ instances.each do |instance|
90
+ printf "%-25s %s\n", instance.name, instance.server_software
91
+ end
92
+ exit 1
93
+ end
94
94
  end
95
95
 
96
96
  def find_instance_by_name_prefix(name)
97
- instance = InstanceRegistry.new.find_by_name_prefix(name)
98
- if instance == :ambigious
99
- abort "ERROR: there are multiple instances whose name start with '#{name}'. Please specify the full name."
100
- elsif instance
101
- return instance
102
- else
103
- abort "ERROR: there doesn't seem to be a #{PROGRAM_NAME} instance running with the name '#{name}'."
104
- end
97
+ instance = InstanceRegistry.new.find_by_name_prefix(name)
98
+ if instance == :ambigious
99
+ abort "ERROR: there are multiple instances whose name start with '#{name}'. Please specify the full name."
100
+ elsif instance
101
+ return instance
102
+ else
103
+ abort "ERROR: there doesn't seem to be a #{PROGRAM_NAME} instance running with the name '#{name}'."
104
+ end
105
105
  end
106
106
 
107
107
  def show_status(instance, options)
108
- print_header(STDOUT, instance) if options[:header]
108
+ print_header(STDOUT, instance) if options[:header]
109
109
 
110
- case options[:show]
111
- when 'pool'
112
- request = Net::HTTP::Get.new("/pool.txt?colorize=#{options[:color]}&verbose=#{options[:verbose]}")
113
- request.basic_auth("ro_admin", obtain_read_only_admin_password(instance))
114
- response = instance.http_request("agents.s/server_admin", request)
115
- if response.code.to_i / 100 == 2
116
- puts response.body
117
- else
118
- STDERR.puts "*** An error occured."
119
- STDERR.puts "#{response.code}: #{response.body}"
120
- exit 2
121
- end
110
+ case options[:show]
111
+ when 'pool'
112
+ request = Net::HTTP::Get.new("/pool.txt?colorize=#{options[:color]}&verbose=#{options[:verbose]}")
113
+ request.basic_auth("ro_admin", obtain_read_only_admin_password(instance))
114
+ response = instance.http_request("agents.s/server_admin", request)
115
+ if response.code.to_i / 100 == 2
116
+ puts response.body
117
+ else
118
+ STDERR.puts "*** An error occured."
119
+ STDERR.puts "#{response.code}: #{response.body}"
120
+ exit 2
121
+ end
122
122
 
123
- when 'requests', 'server'
124
- request = Net::HTTP::Get.new("/server.json")
125
- request.basic_auth("ro_admin", obtain_read_only_admin_password(instance))
126
- response = instance.http_request("agents.s/server_admin", request)
127
- if response.code.to_i / 100 == 2
128
- puts response.body
129
- else
130
- STDERR.puts "*** An error occured."
131
- STDERR.puts "#{response.code}: #{response.body}"
132
- exit 2
133
- end
123
+ when 'requests', 'server'
124
+ request = Net::HTTP::Get.new("/server.json")
125
+ request.basic_auth("ro_admin", obtain_read_only_admin_password(instance))
126
+ response = instance.http_request("agents.s/server_admin", request)
127
+ if response.code.to_i / 100 == 2
128
+ puts response.body
129
+ else
130
+ STDERR.puts "*** An error occured."
131
+ STDERR.puts "#{response.code}: #{response.body}"
132
+ exit 2
133
+ end
134
134
 
135
- when 'backtraces'
136
- request = Net::HTTP::Get.new("/backtraces.txt")
137
- request.basic_auth("ro_admin", obtain_read_only_admin_password(instance))
138
- response = instance.http_request("agents.s/server_admin", request)
139
- if response.code.to_i / 100 == 2
140
- text = response.body
141
- # Colorize output
142
- color = PhusionPassenger::Utils::AnsiColors.new
143
- text.gsub!(/^(Thread .*:)$/, color.black_bg + color.yellow + '\1' + color.reset)
144
- text.gsub!(/^( +in '.*? )(.*?)\(/, '\1' + color.bold + '\2' + color.reset + '(')
145
- puts text
146
- else
147
- STDERR.puts "*** An error occured."
148
- STDERR.puts "#{response.code}: #{response.body}"
149
- exit 2
150
- end
151
-
152
- when 'xml'
153
- request = Net::HTTP::Get.new("/pool.xml")
154
- request.basic_auth("ro_admin", obtain_read_only_admin_password(instance))
155
- response = instance.http_request("agents.s/server_admin", request)
156
- if response.code.to_i / 100 == 2
157
- indented = format_with_xmllint(response.body)
158
- if indented
159
- puts indented
160
- else
161
- puts response.body
162
- STDERR.puts "*** Tip: if you install the 'xmllint' command then the XML output will be indented."
163
- end
164
- else
165
- STDERR.puts "*** An error occured."
166
- STDERR.puts "#{response.code}: #{response.body}"
167
- exit 2
168
- end
135
+ when 'backtraces'
136
+ request = Net::HTTP::Get.new("/backtraces.txt")
137
+ request.basic_auth("ro_admin", obtain_read_only_admin_password(instance))
138
+ response = instance.http_request("agents.s/server_admin", request)
139
+ if response.code.to_i / 100 == 2
140
+ text = response.body
141
+ # Colorize output
142
+ color = PhusionPassenger::Utils::AnsiColors.new
143
+ text.gsub!(/^(Thread .*:)$/, color.black_bg + color.yellow + '\1' + color.reset)
144
+ text.gsub!(/^( +in '.*? )(.*?)\(/, '\1' + color.bold + '\2' + color.reset + '(')
145
+ puts text
146
+ else
147
+ STDERR.puts "*** An error occured."
148
+ STDERR.puts "#{response.code}: #{response.body}"
149
+ exit 2
150
+ end
169
151
 
170
- when 'union_station'
171
- request = Net::HTTP::Get.new("/status.txt")
172
- request.basic_auth("ro_admin", obtain_read_only_admin_password(instance))
173
- response = instance.http_request("agents.s/logging_admin", request)
174
- if response.code.to_i / 100 == 2
175
- puts response.body
176
- else
177
- STDERR.puts "*** An error occured."
178
- STDERR.puts "#{response.code}: #{response.body}"
179
- exit 2
180
- end
181
- end
152
+ when 'xml'
153
+ request = Net::HTTP::Get.new("/pool.xml?secrets=#{options[:verbose]}")
154
+ request.basic_auth("ro_admin", obtain_read_only_admin_password(instance))
155
+ response = instance.http_request("agents.s/server_admin", request)
156
+ if response.code.to_i / 100 == 2
157
+ indented = format_with_xmllint(response.body)
158
+ if indented
159
+ puts indented
160
+ else
161
+ puts response.body
162
+ STDERR.puts "*** Tip: if you install the 'xmllint' command then the XML output will be indented."
163
+ end
164
+ else
165
+ STDERR.puts "*** An error occured."
166
+ STDERR.puts "#{response.code}: #{response.body}"
167
+ exit 2
168
+ end
169
+
170
+ when 'union_station'
171
+ request = Net::HTTP::Get.new("/status.txt")
172
+ request.basic_auth("ro_admin", obtain_read_only_admin_password(instance))
173
+ response = instance.http_request("agents.s/logging_admin", request)
174
+ if response.code.to_i / 100 == 2
175
+ puts response.body
176
+ else
177
+ STDERR.puts "*** An error occured."
178
+ STDERR.puts "#{response.code}: #{response.body}"
179
+ exit 2
180
+ end
181
+ end
182
182
  end
183
183
 
184
184
  def print_header(io, instance)
185
- io.puts "Version : #{PhusionPassenger::VERSION_STRING}"
186
- io.puts "Date : #{Time.now}"
187
- io.puts "Instance: #{instance.name} (#{instance.server_software})"
188
- io.puts
185
+ io.puts "Version : #{PhusionPassenger::VERSION_STRING}"
186
+ io.puts "Date : #{Time.now}"
187
+ io.puts "Instance: #{instance.name} (#{instance.server_software})"
188
+ io.puts
189
189
  end
190
190
 
191
191
  def obtain_read_only_admin_password(instance)
192
- begin
193
- password = instance.read_only_admin_password
194
- rescue Errno::EACCES
195
- print_permission_error_message
196
- exit 2
197
- end
192
+ begin
193
+ password = instance.read_only_admin_password
194
+ rescue Errno::EACCES
195
+ print_permission_error_message
196
+ exit 2
197
+ end
198
198
  end
199
199
 
200
200
  def print_permission_error_message
201
- PhusionPassenger.require_passenger_lib 'platform_info/ruby'
202
- STDERR.puts "*** ERROR: You are not authorized to query the status for this " <<
203
- "#{PROGRAM_NAME} instance. Please try again with '#{PhusionPassenger::PlatformInfo.ruby_sudo_command}'."
201
+ PhusionPassenger.require_passenger_lib 'platform_info/ruby'
202
+ STDERR.puts "*** ERROR: You are not authorized to query the status for this " <<
203
+ "#{PROGRAM_NAME} instance. Please try again with '#{PhusionPassenger::PlatformInfo.ruby_sudo_command}'."
204
204
  end
205
205
 
206
206
  def format_with_xmllint(xml)
207
- return nil if !PhusionPassenger::PlatformInfo.find_command('xmllint')
208
- require 'open3'
209
- require 'thread'
210
- ENV['XMLLINT_INDENT'] = ' '
211
- Open3.popen3("xmllint", "--format", "-") do |stdin, stdout, stderr|
212
- stdout_text = nil
213
- stderr_text = nil
214
- thread1 = Thread.new do
215
- stdin.write(xml)
216
- stdin.close
217
- end
218
- thread2 = Thread.new do
219
- stdout_text = stdout.read
220
- stdout.close
221
- end
222
- thread3 = Thread.new do
223
- stderr_text = stderr.read
224
- stderr.close
225
- end
226
- thread1.join
227
- thread2.join
228
- thread3.join
229
-
230
- if stdout_text.nil? || stdout_text.empty?
231
- if stderr_text !~ /No such file or directory/ && stderr_text !~ /command not found/
232
- STDERR.puts stderr_text
233
- end
234
- return nil
235
- else
236
- return stdout_text
237
- end
238
- end
207
+ return nil if !PhusionPassenger::PlatformInfo.find_command('xmllint')
208
+ require 'open3'
209
+ require 'thread'
210
+ ENV['XMLLINT_INDENT'] = ' '
211
+ Open3.popen3("xmllint", "--format", "-") do |stdin, stdout, stderr|
212
+ stdout_text = nil
213
+ stderr_text = nil
214
+ thread1 = Thread.new do
215
+ stdin.write(xml)
216
+ stdin.close
217
+ end
218
+ thread2 = Thread.new do
219
+ stdout_text = stdout.read
220
+ stdout.close
221
+ end
222
+ thread3 = Thread.new do
223
+ stderr_text = stderr.read
224
+ stderr.close
225
+ end
226
+ thread1.join
227
+ thread2.join
228
+ thread3.join
229
+
230
+ if stdout_text.nil? || stdout_text.empty?
231
+ if stderr_text !~ /No such file or directory/ && stderr_text !~ /command not found/
232
+ STDERR.puts stderr_text
233
+ end
234
+ return nil
235
+ else
236
+ return stdout_text
237
+ end
238
+ end
239
239
  end
240
240
 
241
241
 
242
242
  ##### Main command dispatcher #####
243
243
 
244
244
  def create_option_parser(options)
245
- return OptionParser.new do |opts|
246
- nl = "\n" << " " * 37
247
- opts.banner = "Usage: passenger-status [options] [instance name]"
248
- opts.separator ""
249
- opts.separator "Tool for inspecting Phusion Passenger's internal status."
250
- opts.separator ""
245
+ return OptionParser.new do |opts|
246
+ nl = "\n" << " " * 37
247
+ opts.banner = "Usage: passenger-status [options] [instance name]"
248
+ opts.separator ""
249
+ opts.separator "Tool for inspecting Phusion Passenger's internal status."
250
+ opts.separator ""
251
251
 
252
- opts.separator "Options:"
253
- opts.on("--show=pool|server|backtraces|xml|union_station", String,
254
- "Whether to show the pool's contents,#{nl}" <<
255
- "the currently running requests,#{nl}" <<
256
- "the backtraces of all threads or an XML#{nl}" <<
257
- "description of the pool.") do |what|
258
- if what !~ /\A(pool|server|requests|backtraces|xml|union_station)\Z/
259
- STDERR.puts "Invalid argument for --show."
260
- exit 1
261
- else
262
- options[:show] = what
263
- end
264
- end
265
- opts.on("--no-header", "Do not display an informative header#{nl}" <<
266
- "containing the timestamp, version number,#{nl}" <<
267
- "etc.") do
268
- options[:header] = false
269
- end
270
- opts.on("--force-colors", "Display colors even if stdout is not a TTY") do
271
- options[:color] = true
272
- end
273
- opts.on("--verbose", "-v", "Show verbose information.") do
274
- options[:verbose] = true
275
- end
276
- end
252
+ opts.separator "Options:"
253
+ opts.on("--show=pool|server|backtraces|xml|union_station", String,
254
+ "Whether to show the pool's contents,#{nl}" <<
255
+ "the currently running requests,#{nl}" <<
256
+ "the backtraces of all threads or an XML#{nl}" <<
257
+ "description of the pool.") do |what|
258
+ if what !~ /\A(pool|server|requests|backtraces|xml|union_station)\Z/
259
+ STDERR.puts "Invalid argument for --show."
260
+ exit 1
261
+ else
262
+ options[:show] = what
263
+ end
264
+ end
265
+ opts.on("--no-header", "Do not display an informative header#{nl}" <<
266
+ "containing the timestamp, version number,#{nl}" <<
267
+ "etc.") do
268
+ options[:header] = false
269
+ end
270
+ opts.on("--force-colors", "Display colors even if stdout is not a TTY") do
271
+ options[:color] = true
272
+ end
273
+ opts.on("--verbose", "-v", "Show verbose information.") do
274
+ options[:verbose] = true
275
+ end
276
+ end
277
277
  end
278
278
 
279
279
  def parse_argv
280
- options = DEFAULT_OPTIONS.dup
281
- parser = create_option_parser(options)
282
- begin
283
- parser.parse!
284
- rescue OptionParser::ParseError => e
285
- puts e
286
- puts
287
- puts "Please see '--help' for valid options."
288
- exit 1
289
- end
280
+ options = DEFAULT_OPTIONS.dup
281
+ parser = create_option_parser(options)
282
+ begin
283
+ parser.parse!
284
+ rescue OptionParser::ParseError => e
285
+ puts e
286
+ puts
287
+ puts "Please see '--help' for valid options."
288
+ exit 1
289
+ end
290
290
 
291
- return options
291
+ return options
292
292
  end
293
293
 
294
294
  def infer_command
295
- if !ARGV[0] || ARGV[0] !~ /^-/
296
- return [:show_status, ARGV.dup]
297
- else
298
- command_name, *argv = ARGV
299
- if respond_to?("command_#{command_name}")
300
- return [command_name, argv]
301
- else
302
- abort "ERROR: unrecognized command '#{command_name}'"
303
- end
304
- end
295
+ if !ARGV[0] || ARGV[0] !~ /^-/
296
+ return [:show_status, ARGV.dup]
297
+ else
298
+ command_name, *argv = ARGV
299
+ if respond_to?("command_#{command_name}")
300
+ return [command_name, argv]
301
+ else
302
+ abort "ERROR: unrecognized command '#{command_name}'"
303
+ end
304
+ end
305
305
  end
306
306
 
307
307
  def start
308
- options = parse_argv
309
- command, argv = infer_command
310
- send("command_#{command}", argv, options)
308
+ options = parse_argv
309
+ command, argv = infer_command
310
+ send("command_#{command}", argv, options)
311
311
  end
312
312
 
313
313
  start