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
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: passenger
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.0.beta3
4
+ version: 5.0.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Phusion - http://www.phusion.nl/
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-09 00:00:00.000000000 Z
11
+ date: 2015-02-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - ! '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.8.1
27
- - !ruby/object:Gem::Dependency
28
- name: daemon_controller
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ! '>='
32
- - !ruby/object:Gem::Version
33
- version: 1.2.0
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ! '>='
39
- - !ruby/object:Gem::Version
40
- version: 1.2.0
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: rack
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -2750,6 +2736,7 @@ files:
2750
2736
  - ext/ruby/extconf.rb
2751
2737
  - ext/ruby/passenger_native_support.c
2752
2738
  - helper-scripts/backtrace-sanitizer.rb
2739
+ - helper-scripts/crash-watch.rb
2753
2740
  - helper-scripts/download_binaries/extconf.rb
2754
2741
  - helper-scripts/meteor-loader.rb
2755
2742
  - helper-scripts/node-loader.js
@@ -2826,11 +2813,9 @@ files:
2826
2813
  - lib/phusion_passenger/simple_benchmarking.rb
2827
2814
  - lib/phusion_passenger/standalone/app_finder.rb
2828
2815
  - lib/phusion_passenger/standalone/command.rb
2829
- - lib/phusion_passenger/standalone/command2.rb
2830
2816
  - lib/phusion_passenger/standalone/config_utils.rb
2831
2817
  - lib/phusion_passenger/standalone/control_utils.rb
2832
2818
  - lib/phusion_passenger/standalone/main.rb
2833
- - lib/phusion_passenger/standalone/start2_command.rb
2834
2819
  - lib/phusion_passenger/standalone/start_command.rb
2835
2820
  - lib/phusion_passenger/standalone/start_command/builtin_engine.rb
2836
2821
  - lib/phusion_passenger/standalone/start_command/nginx_engine.rb
@@ -2854,6 +2839,13 @@ files:
2854
2839
  - lib/phusion_passenger/utils/terminal_choice_menu.rb
2855
2840
  - lib/phusion_passenger/utils/tmpio.rb
2856
2841
  - lib/phusion_passenger/utils/unseekable_socket.rb
2842
+ - lib/phusion_passenger/vendor/crash_watch/app.rb
2843
+ - lib/phusion_passenger/vendor/crash_watch/gdb_controller.rb
2844
+ - lib/phusion_passenger/vendor/crash_watch/version.rb
2845
+ - lib/phusion_passenger/vendor/daemon_controller.rb
2846
+ - lib/phusion_passenger/vendor/daemon_controller/lock_file.rb
2847
+ - lib/phusion_passenger/vendor/daemon_controller/spawn.rb
2848
+ - lib/phusion_passenger/vendor/daemon_controller/version.rb
2857
2849
  - man/passenger-config.1
2858
2850
  - man/passenger-memory-stats.8
2859
2851
  - man/passenger-status.8
@@ -2937,6 +2929,7 @@ files:
2937
2929
  - resources/templates/config/installation_utils/support_binaries_dir_not_writable_despite_running_as_root.txt.erb
2938
2930
  - resources/templates/config/installation_utils/unexpected_filesystem_problem.txt.erb
2939
2931
  - resources/templates/config/installation_utils/user_support_binaries_dir_not_writable.txt.erb
2932
+ - resources/templates/config/nginx_engine_compiler/possible_solutions_for_download_and_extraction_problems.txt.erb
2940
2933
  - resources/templates/error_layout.css
2941
2934
  - resources/templates/error_layout.html.template
2942
2935
  - resources/templates/general_error.html.template
@@ -2963,9 +2956,6 @@ files:
2963
2956
  - resources/templates/nginx/welcome.txt.erb
2964
2957
  - resources/templates/standalone/cannot_write_to_dir.txt.erb
2965
2958
  - resources/templates/standalone/config.erb
2966
- - resources/templates/standalone/download_tool_missing.txt.erb
2967
- - resources/templates/standalone/possible_solutions_for_download_and_extraction_problems.txt.erb
2968
- - resources/templates/standalone/run_installer_as_root.txt.erb
2969
2959
  - resources/templates/undisclosed_error.html.template
2970
2960
  - resources/union_station_gateway.crt
2971
2961
  - test/.rspec
metadata.gz.asc CHANGED
@@ -2,11 +2,11 @@
2
2
  Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
3
3
  Comment: GPGTools - http://gpgtools.org
4
4
 
5
- iQEcBAABAgAGBQJU2MfwAAoJECrHRaUKISqMPmYIAKtrMbpRJ2DHxagF3AnOV7xM
6
- LzLmXQ8mTHZdd1fL2DJmWHISF0y9FQKseLrStQbq9G/tPTaAzNEwF9Z/Jc952Z7n
7
- 7rx/FGkwzAJdqlgVWsMC18CvZY5UHirzvvMnkCG146X6w/sybWA3FhKy13pkUZh9
8
- 9CKT1RVlDR+jciUKOsE6AZXdLHv6Dsy/9Egy9fgqQbJV9NAMgO7dQ8xBx2GJgUX1
9
- QKiGxMX5thOkNTLlZ+Xjw7t5RyR778Jka+UN2pfNaRy749Z9wWoImZpgKRAQEwF4
10
- lgp7UNO8eMwgCE0cagIAcpVwSxVuI139ux8rk4E0zmHOKIUpqUtOWI3dB1oPsAw=
11
- =YYe9
5
+ iQEcBAABAgAGBQJU5fgMAAoJECrHRaUKISqM2W8IAIiE6ZNzN5Z8ZOJl04ujPwph
6
+ HsyNPbuc/hokEeFf2rxsNM9T6JgsihckDMWHInNpEGx1xM+5sMNJ8Qka4RW4SImA
7
+ Neb9Q8LIMI5onbNut1u4r8NZAd6D+LJEwyvMoKW5BLtVTLM4nDcN9ck+FLXG+Hi4
8
+ /gclwWQixnxeMyi209hJpQrd6xzXmbj7yhsh3IruunnZYnMEVtyutZuLyTBPTg8g
9
+ 5JyukZ4M7z0MyQRmSDWm0BsVUjjDwz1PWyfoYn8rfTGCbKF5DioKQlKkT1RI46EL
10
+ gpJzP4IzyZTSOmbBH47LWudsDG2sYETcKQHluxX5fHgP9d/RRUJYGFWOrwhT9zI=
11
+ =VpfF
12
12
  -----END PGP SIGNATURE-----
@@ -1,292 +0,0 @@
1
- # Phusion Passenger - https://www.phusionpassenger.com/
2
- # Copyright (c) 2010-2014 Phusion
3
- #
4
- # "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
5
- #
6
- # Permission is hereby granted, free of charge, to any person obtaining a copy
7
- # of this software and associated documentation files (the "Software"), to deal
8
- # in the Software without restriction, including without limitation the rights
9
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
- # copies of the Software, and to permit persons to whom the Software is
11
- # furnished to do so, subject to the following conditions:
12
- #
13
- # The above copyright notice and this permission notice shall be included in
14
- # all copies or substantial portions of the Software.
15
- #
16
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
- # THE SOFTWARE.
23
- require 'optparse'
24
- PhusionPassenger.require_passenger_lib 'constants'
25
- PhusionPassenger.require_passenger_lib 'ruby_core_enhancements'
26
- PhusionPassenger.require_passenger_lib 'utils'
27
- PhusionPassenger.require_passenger_lib 'standalone/utils'
28
-
29
- module PhusionPassenger
30
- module Standalone
31
-
32
- class Command
33
- DEFAULT_OPTIONS = {
34
- :address => '0.0.0.0',
35
- :port => 3000,
36
- :environment => ENV['RAILS_ENV'] || ENV['RACK_ENV'] || ENV['NODE_ENV'] || ENV['PASSENGER_APP_ENV'] || 'development',
37
- :max_pool_size => 6,
38
- :min_instances => 1,
39
- :spawn_method => Kernel.respond_to?(:fork) ? 'smart' : 'direct',
40
- :concurrency_model => DEFAULT_CONCURRENCY_MODEL,
41
- :thread_count => DEFAULT_THREAD_COUNT,
42
- :nginx_version => PREFERRED_NGINX_VERSION
43
- }.freeze
44
-
45
- include Utils
46
-
47
- def self.show_in_command_list
48
- return true
49
- end
50
-
51
- def self.description
52
- return nil
53
- end
54
-
55
- def initialize(args)
56
- @args = args.dup
57
- @original_args = args.dup
58
- @options = DEFAULT_OPTIONS.dup
59
- end
60
-
61
- private
62
- def require_daemon_controller
63
- if !defined?(DaemonController)
64
- begin
65
- require 'daemon_controller'
66
- begin
67
- require 'daemon_controller/version'
68
- too_old = DaemonController::VERSION_STRING < '1.1.0'
69
- rescue LoadError
70
- too_old = true
71
- end
72
- if too_old
73
- PhusionPassenger.require_passenger_lib 'platform_info/ruby'
74
- gem_command = PlatformInfo.gem_command(:sudo => true)
75
- error "Your version of daemon_controller is too old. " <<
76
- "You must install 1.1.0 or later. Please upgrade:\n\n" <<
77
-
78
- " #{gem_command} uninstall FooBarWidget-daemon_controller\n" <<
79
- " #{gem_command} install daemon_controller",
80
- :wrap => false
81
- exit 1
82
- end
83
- rescue LoadError
84
- PhusionPassenger.require_passenger_lib 'platform_info/ruby'
85
- gem_command = PlatformInfo.gem_command(:sudo => true)
86
- error "Please install daemon_controller first:\n\n" <<
87
- " #{gem_command} install daemon_controller"
88
- exit 1
89
- end
90
- end
91
- end
92
-
93
- def require_erb
94
- require 'erb' unless defined?(ERB)
95
- end
96
-
97
- def require_etc
98
- require 'etc' unless defined?(Etc)
99
- end
100
-
101
- def require_optparse
102
- require 'optparse' unless defined?(OptionParser)
103
- end
104
-
105
- def require_app_finder
106
- PhusionPassenger.require_passenger_lib 'standalone/app_finder' unless defined?(AppFinder)
107
- end
108
-
109
- def debugging?
110
- return ENV['PASSENGER_DEBUG'] && !ENV['PASSENGER_DEBUG'].empty?
111
- end
112
-
113
- def parse_options!(command_name, description = nil)
114
- require_etc
115
- help = false
116
-
117
- home_dir = PhusionPassenger.home_dir
118
- global_config_file = File.join(home_dir, USER_NAMESPACE_DIRNAME, "standalone", "config")
119
- if File.exist?(global_config_file)
120
- PhusionPassenger.require_passenger_lib 'standalone/config_file' unless defined?(ConfigFile)
121
- global_options = ConfigFile.new(:global_config, global_config_file).options
122
- @options.merge!(global_options)
123
- end
124
-
125
- require_optparse
126
- parser = OptionParser.new do |opts|
127
- opts.banner = "Usage: passenger #{command_name} [options]"
128
- opts.separator description if description
129
- opts.separator " "
130
- yield opts
131
- opts.on("-h", "--help", "Show this help message") do
132
- help = true
133
- end
134
- end
135
- parser.parse!(@args)
136
- if help
137
- puts parser
138
- exit 0
139
- end
140
- end
141
-
142
- def error(message, options = {})
143
- wrap = options.fetch(:wrap, true)
144
- if message =~ /\n/
145
- if wrap
146
- processed_message = wrap_desc(message, 80, 0)
147
- else
148
- processed_message = message
149
- end
150
- STDERR.puts("*** ERROR ***\n" << processed_message)
151
- else
152
- if wrap
153
- processed_message = wrap_desc("*** ERROR: #{message}", 80, 0)
154
- else
155
- processed_message = "*** ERROR: #{message}"
156
- end
157
- STDERR.puts(processed_message)
158
- end
159
- @plugin.call_hook(:error, message) if @plugin
160
- end
161
-
162
- # Word wrap the given option description text so that it is formatted
163
- # nicely in the --help output.
164
- def wrap_desc(description_text, max_width = 43, newline_prefix_size = 37)
165
- line_prefix = "\n" << (' ' * newline_prefix_size)
166
- result = description_text.gsub(/(.{1,#{max_width}})( +|$\n?)|(.{1,#{max_width}})/, "\\1\\3#{line_prefix}")
167
- result.strip!
168
- return result
169
- end
170
-
171
- def ensure_directory_exists(dir)
172
- if !File.exist?(dir)
173
- require_file_utils
174
- FileUtils.mkdir_p(dir)
175
- end
176
- end
177
-
178
- def determine_various_resource_locations(create_subdirs = true)
179
- require_app_finder
180
- if @options[:socket_file]
181
- pid_basename = "passenger.pid"
182
- log_basename = "passenger.log"
183
- else
184
- pid_basename = "passenger.#{@options[:port]}.pid"
185
- log_basename = "passenger.#{@options[:port]}.log"
186
- end
187
- if @args.empty?
188
- if AppFinder.looks_like_app_directory?(".")
189
- @options[:pid_file] ||= File.absolute_path_no_resolve("tmp/pids/#{pid_basename}")
190
- @options[:log_file] ||= File.absolute_path_no_resolve("log/#{log_basename}")
191
- if create_subdirs
192
- ensure_directory_exists(File.dirname(@options[:pid_file]))
193
- ensure_directory_exists(File.dirname(@options[:log_file]))
194
- end
195
- else
196
- @options[:pid_file] ||= File.absolute_path_no_resolve(pid_basename)
197
- @options[:log_file] ||= File.absolute_path_no_resolve(log_basename)
198
- end
199
- else
200
- @options[:pid_file] ||= File.absolute_path_no_resolve(File.join(@args[0], pid_basename))
201
- @options[:log_file] ||= File.absolute_path_no_resolve(File.join(@args[0], log_basename))
202
- end
203
- end
204
-
205
- def write_nginx_config_file
206
- PhusionPassenger.require_passenger_lib 'platform_info/ruby'
207
- PhusionPassenger.require_passenger_lib 'utils/tmpio'
208
- # @temp_dir may already be set because we're redeploying
209
- # using Mass Deployment.
210
- @temp_dir ||= PhusionPassenger::Utils.mktmpdir(
211
- "passenger-standalone.")
212
- @config_filename = "#{@temp_dir}/config"
213
- File.chmod(0755, @temp_dir)
214
- begin
215
- Dir.mkdir("#{@temp_dir}/logs")
216
- rescue Errno::EEXIST
217
- end
218
-
219
- File.open(@config_filename, 'w') do |f|
220
- f.chmod(0644)
221
- require_erb
222
- erb = ERB.new(File.read(nginx_config_template_filename), nil, "-")
223
- current_user = Etc.getpwuid(Process.uid).name
224
-
225
- # The template requires some helper methods which are defined in start_command.rb.
226
- output = erb.result(binding)
227
- f.write(output)
228
- puts output if debugging?
229
- end
230
- end
231
-
232
- def nginx_config_template_filename
233
- if @options[:nginx_config_template]
234
- return @options[:nginx_config_template]
235
- else
236
- return File.join(PhusionPassenger.resources_dir,
237
- "templates", "standalone", "config.erb")
238
- end
239
- end
240
-
241
- def boolean_config_value(val)
242
- return val ? "on" : "off"
243
- end
244
-
245
- def serialize_strset(*items)
246
- if "".respond_to?(:force_encoding)
247
- items = items.map { |x| x.force_encoding('binary') }
248
- null = "\0".force_encoding('binary')
249
- else
250
- null = "\0"
251
- end
252
- return [items.join(null)].pack('m*').gsub("\n", "").strip
253
- end
254
-
255
- def determine_nginx_start_command
256
- return "#{@nginx_binary} -c '#{@config_filename}' -p '#{@temp_dir}/'"
257
- end
258
-
259
- # Returns the port on which to ping Nginx.
260
- def nginx_ping_port
261
- if @options[:ping_port]
262
- return @options[:ping_port]
263
- else
264
- return @options[:port]
265
- end
266
- end
267
-
268
- def create_nginx_controller(extra_options = {})
269
- require_daemon_controller
270
- require 'socket' unless defined?(UNIXSocket)
271
- require 'thread' unless defined?(Mutex)
272
- if @options[:socket_file]
273
- ping_spec = [:unix, @options[:socket_file]]
274
- else
275
- ping_spec = [:tcp, @options[:address], nginx_ping_port]
276
- end
277
- opts = {
278
- :identifier => 'Nginx',
279
- :before_start => method(:write_nginx_config_file),
280
- :start_command => method(:determine_nginx_start_command),
281
- :ping_command => ping_spec,
282
- :pid_file => @options[:pid_file],
283
- :log_file => @options[:log_file],
284
- :timeout => 25
285
- }
286
- @nginx = DaemonController.new(opts.merge(extra_options))
287
- @nginx_mutex = Mutex.new
288
- end
289
- end
290
-
291
- end # module Standalone
292
- end # module PhusionPassenger
@@ -1,799 +0,0 @@
1
- # Phusion Passenger - https://www.phusionpassenger.com/
2
- # Copyright (c) 2010-2014 Phusion
3
- #
4
- # "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
5
- #
6
- # Permission is hereby granted, free of charge, to any person obtaining a copy
7
- # of this software and associated documentation files (the "Software"), to deal
8
- # in the Software without restriction, including without limitation the rights
9
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
- # copies of the Software, and to permit persons to whom the Software is
11
- # furnished to do so, subject to the following conditions:
12
- #
13
- # The above copyright notice and this permission notice shall be included in
14
- # all copies or substantial portions of the Software.
15
- #
16
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
- # THE SOFTWARE.
23
- require 'socket'
24
- require 'thread'
25
- require 'etc'
26
- PhusionPassenger.require_passenger_lib 'constants'
27
- PhusionPassenger.require_passenger_lib 'plugin'
28
- PhusionPassenger.require_passenger_lib 'ruby_core_enhancements'
29
- PhusionPassenger.require_passenger_lib 'standalone/command'
30
- PhusionPassenger.require_passenger_lib 'platform_info/operating_system'
31
-
32
- # We lazy load as many libraries as possible not only to improve startup performance,
33
- # but also to ensure that we don't require libraries before we've passed the dependency
34
- # checking stage of the runtime installer.
35
-
36
- module PhusionPassenger
37
- module Standalone
38
-
39
- class StartCommand < Command
40
- def self.description
41
- return "Start Phusion Passenger Standalone."
42
- end
43
-
44
- def initialize(args)
45
- super(args)
46
- @console_mutex = Mutex.new
47
- @termination_pipe = IO.pipe
48
- @threads = []
49
- @interruptable_threads = []
50
- @plugin = PhusionPassenger::Plugin.new('standalone/start_command', self, @options)
51
- end
52
-
53
- def run
54
- parse_my_options
55
-
56
- ensure_runtime_installed
57
- set_stdout_stderr_binmode
58
- exit if @options[:runtime_check_only]
59
- require_app_finder
60
- @app_finder = AppFinder.new(@args, @options)
61
- @apps = @app_finder.scan
62
- @options = @app_finder.global_options
63
- sanity_check_server_options
64
- determine_various_resource_locations
65
- @plugin.call_hook(:found_apps, @apps)
66
-
67
- extra_controller_options = {}
68
- @plugin.call_hook(:before_creating_nginx_controller, extra_controller_options)
69
- create_nginx_controller(extra_controller_options)
70
-
71
- begin
72
- start_nginx
73
- show_intro_message
74
- if @options[:daemonize]
75
- if PlatformInfo.ruby_supports_fork?
76
- daemonize
77
- else
78
- daemonize_without_fork
79
- end
80
- end
81
- Thread.abort_on_exception = true
82
- @plugin.call_hook(:nginx_started, @nginx)
83
- ########################
84
- ########################
85
- touch_temp_dir_in_background
86
- watch_log_files_in_background if should_watch_logs?
87
- wait_until_nginx_has_exited if should_wait_until_nginx_has_exited?
88
- rescue Interrupt
89
- begin_shutdown
90
- stop_threads
91
- stop_nginx
92
- exit 2
93
- rescue SignalException => signal
94
- begin_shutdown
95
- stop_threads
96
- stop_nginx
97
- if signal.message == 'SIGINT' || signal.message == 'SIGTERM'
98
- exit 2
99
- else
100
- raise
101
- end
102
- rescue Exception => e
103
- begin_shutdown
104
- stop_threads
105
- stop_nginx
106
- raise
107
- ensure
108
- begin_shutdown
109
- begin
110
- stop_threads
111
- ensure
112
- finalize_shutdown
113
- end
114
- end
115
- ensure
116
- @plugin.call_hook(:cleanup)
117
- end
118
-
119
- private
120
- def require_file_utils
121
- require 'fileutils' unless defined?(FileUtils)
122
- end
123
-
124
- def parse_my_options
125
- description = "Starts Phusion Passenger Standalone and serve one or more Ruby web applications."
126
- parse_options!("start [directory]", description) do |opts|
127
- opts.separator "Server options:"
128
- opts.on("-a", "--address HOST", String,
129
- wrap_desc("Bind to HOST address (default: #{@options[:address]})")) do |value|
130
- @options[:address] = value
131
- @options[:tcp_explicitly_given] = true
132
- end
133
- opts.on("-p", "--port NUMBER", Integer,
134
- wrap_desc("Use the given port number (default: #{@options[:port]})")) do |value|
135
- @options[:port] = value
136
- @options[:tcp_explicitly_given] = true
137
- end
138
- opts.on("-S", "--socket FILE", String,
139
- wrap_desc("Bind to Unix domain socket instead of TCP socket")) do |value|
140
- @options[:socket_file] = value
141
- end
142
- opts.on("--ssl",
143
- wrap_desc("Enable SSL support")) do
144
- @options[:ssl] = true
145
- end
146
- opts.on("--ssl-certificate PATH", String,
147
- wrap_desc("Specify the SSL certificate path")) do |val|
148
- @options[:ssl_certificate] = File.absolute_path_no_resolve(val)
149
- end
150
- opts.on("--ssl-certificate-key PATH", String,
151
- wrap_desc("Specify the SSL key path")) do |val|
152
- @options[:ssl_certificate_key] = File.absolute_path_no_resolve(val)
153
- end
154
- opts.on("--ssl-port PORT", Integer,
155
- wrap_desc("Listen for SSL on this port, while listening for HTTP on the normal port")) do |val|
156
- @options[:ssl_port] = val
157
- end
158
- opts.on("-d", "--daemonize",
159
- wrap_desc("Daemonize into the background")) do
160
- @options[:daemonize] = true
161
- end
162
- opts.on("--user USERNAME", String,
163
- wrap_desc("User to run as. Ignored unless running as root.")) do |value|
164
- @options[:user] = value
165
- end
166
- opts.on("--log-file FILENAME", String,
167
- wrap_desc("Where to write log messages (default: console, or /dev/null when daemonized)")) do |value|
168
- @options[:log_file] = value
169
- end
170
- opts.on("--pid-file FILENAME", String,
171
- wrap_desc("Where to store the PID file")) do |value|
172
- @options[:pid_file] = value
173
- end
174
- opts.on("--instance-registry-dir PATH", String,
175
- wrap_desc("Use the given instance registry directory")) do |value|
176
- @options[:instance_registry_dir] = value
177
- end
178
- opts.on("--data-buffer-dir PATH", String,
179
- wrap_desc("Use the given data buffer directory")) do |value|
180
- @options[:data_buffer_dir] = value
181
- end
182
-
183
- opts.separator ""
184
- opts.separator "Application loading options:"
185
- opts.on("-e", "--environment ENV", String,
186
- wrap_desc("Framework environment (default: #{@options[:environment]})")) do |value|
187
- @options[:environment] = value
188
- end
189
- opts.on("-R", "--rackup FILE", String,
190
- wrap_desc("Consider application a Ruby Rack app, and use the given rackup file")) do |value|
191
- @options[:app_type] = "rack"
192
- @options[:startup_file] = value
193
- end
194
- opts.on("--app-type NAME", String,
195
- wrap_desc("Force app to be detected as the given type")) do |value|
196
- @options[:app_type] = value
197
- end
198
- opts.on("--startup-file FILENAME", String,
199
- wrap_desc("Force given startup file to be used")) do |value|
200
- @options[:startup_file] = value
201
- end
202
- opts.on("--spawn-method NAME", String,
203
- wrap_desc("The spawn method to use (default: #{@options[:spawn_method]})")) do |value|
204
- @options[:spawn_method] = value
205
- end
206
- opts.on("--static-files-dir PATH", String,
207
- wrap_desc("Specify the static files dir")) do |val|
208
- @options[:static_files_dir] = File.absolute_path_no_resolve(val)
209
- end
210
- opts.on("--restart-dir PATH", String,
211
- wrap_desc("Specify the restart dir")) do |val|
212
- @options[:restart_dir] = File.absolute_path_no_resolve(val)
213
- end
214
- opts.on("--friendly-error-pages",
215
- wrap_desc("Turn on friendly error pages")) do
216
- @options[:friendly_error_pages] = true
217
- end
218
- opts.on("--no-friendly-error-pages",
219
- wrap_desc("Turn off friendly error pages")) do
220
- @options[:friendly_error_pages] = false
221
- end
222
- opts.on("--load-shell-envvars",
223
- wrap_desc("Load shell startup files before loading application")) do
224
- @options[:load_shell_envvars] = true
225
- end
226
-
227
- opts.separator ""
228
- opts.separator "Process management options:"
229
- opts.on("--max-pool-size NUMBER", Integer,
230
- wrap_desc("Maximum number of application processes (default: #{@options[:max_pool_size]})")) do |value|
231
- @options[:max_pool_size] = value
232
- end
233
- opts.on("--min-instances NUMBER", Integer,
234
- wrap_desc("Minimum number of processes per application (default: #{@options[:min_instances]})")) do |value|
235
- @options[:min_instances] = value
236
- end
237
- opts.on("--concurrency-model NAME", String,
238
- wrap_desc("The concurrency model to use, either 'process' or 'thread' (default: #{@options[:concurrency_model]}) (Enterprise only)")) do |value|
239
- @options[:concurrency_model] = value
240
- end
241
- opts.on("--thread-count NAME", Integer,
242
- wrap_desc("The number of threads to use when using the 'thread' concurrency model (default: #{@options[:thread_count]}) (Enterprise only)")) do |value|
243
- @options[:thread_count] = value
244
- end
245
- opts.on("--rolling-restarts",
246
- wrap_desc("Enable rolling restarts (Enterprise only)")) do
247
- @options[:rolling_restarts] = true
248
- end
249
- opts.on("--resist-deployment-errors",
250
- wrap_desc("Enable deployment error resistance (Enterprise only)")) do
251
- @options[:resist_deployment_errors] = true
252
- end
253
-
254
- opts.separator ""
255
- opts.separator "Request handling options:"
256
- opts.on("--sticky-sessions",
257
- wrap_desc("Enable sticky sessions")) do
258
- @options[:sticky_sessions] = true
259
- end
260
- opts.on("--sticky-sessions-cookie-name", String,
261
- wrap_desc("Cookie name to use for sticky sessions (default: #{DEFAULT_STICKY_SESSIONS_COOKIE_NAME})")) do |val|
262
- @options[:sticky_sessions_cookie_name] = val
263
- end
264
-
265
- opts.separator ""
266
- opts.separator "Union Station options:"
267
- opts.on("--union-station-gateway HOST:PORT", String,
268
- wrap_desc("Specify Union Station Gateway host and port")) do |value|
269
- host, port = value.split(":", 2)
270
- port = port.to_i
271
- port = 443 if port == 0
272
- @options[:union_station_gateway_address] = host
273
- @options[:union_station_gateway_port] = port.to_i
274
- end
275
- opts.on("--union-station-key KEY", String,
276
- wrap_desc("Specify Union Station key")) do |value|
277
- @options[:union_station_key] = value
278
- end
279
-
280
- opts.separator ""
281
- opts.separator "Advanced options:"
282
- opts.on("--ping-port NUMBER", Integer,
283
- wrap_desc("Use the given port number for checking whether Nginx is alive (default: same as the normal port)")) do |value|
284
- @options[:ping_port] = value
285
- end
286
- opts.on("--nginx-bin FILENAME", String,
287
- wrap_desc("Nginx binary to use as core")) do |value|
288
- @options[:nginx_bin] = value
289
- end
290
- opts.on("--nginx-version VERSION", String,
291
- wrap_desc("Nginx version to use as core (default: #{@options[:nginx_version]})")) do |value|
292
- @options[:nginx_version] = value
293
- end
294
- opts.on("--nginx-tarball FILENAME", String,
295
- wrap_desc("If Nginx needs to be installed, then the given tarball will " +
296
- "be used instead of downloading from the Internet")) do |value|
297
- @options[:nginx_tarball] = File.absolute_path_no_resolve(value)
298
- end
299
- opts.on("--nginx-config-template FILENAME", String,
300
- wrap_desc("The template to use for generating the Nginx config file")) do |value|
301
- @options[:nginx_config_template] = File.absolute_path_no_resolve(value)
302
- end
303
- opts.on("--binaries-url-root URL", String,
304
- wrap_desc("If Nginx needs to be installed, then the specified URL will be " +
305
- "checked for binaries prior to a local build.")) do |value|
306
- @options[:binaries_url_root] = value
307
- end
308
- opts.on("--no-download-binaries",
309
- wrap_desc("Never download binaries")) do
310
- @options[:download_binaries] = false
311
- end
312
- opts.on("--runtime-check-only",
313
- wrap_desc("Quit after checking whether the Phusion Passenger Standalone runtime files are installed")) do
314
- @options[:runtime_check_only] = true
315
- end
316
- opts.on("--no-install-runtime",
317
- wrap_desc("Abort if runtime must be installed")) do
318
- @options[:dont_install_runtime] = true
319
- end
320
- opts.on("--no-compile-runtime",
321
- wrap_desc("Abort if runtime must be compiled")) do
322
- @options[:dont_compile_runtime] = true
323
- end
324
-
325
- @plugin.call_hook(:parse_options, opts)
326
- opts.separator ""
327
- end
328
- @plugin.call_hook(:done_parsing_options)
329
- end
330
-
331
- def sanity_check_server_options
332
- if @options[:tcp_explicitly_given] && @options[:socket_file]
333
- error "You cannot specify both --address/--port and --socket. Please choose either one."
334
- exit 1
335
- end
336
- if @options[:ssl] && !@options[:ssl_certificate]
337
- error "You specified --ssl. Please specify --ssl-certificate as well."
338
- exit 1
339
- end
340
- if @options[:ssl] && !@options[:ssl_certificate_key]
341
- error "You specified --ssl. Please specify --ssl-certificate-key as well."
342
- exit 1
343
- end
344
- check_port_bind_permission_and_display_sudo_suggestion
345
- check_port_availability
346
- end
347
-
348
- # Most platforms don't allow non-root processes to bind to a port lower than 1024.
349
- # Check whether this is the case for the current platform and if so, tell the user
350
- # that it must re-run Phusion Passenger Standalone with sudo.
351
- def check_port_bind_permission_and_display_sudo_suggestion
352
- if !@options[:socket_file] && @options[:port] < 1024 && Process.euid != 0
353
- begin
354
- TCPServer.new('127.0.0.1', @options[:port]).close
355
- rescue Errno::EACCES
356
- PhusionPassenger.require_passenger_lib 'platform_info/ruby'
357
- myself = `whoami`.strip
358
- error "Only the 'root' user can run this program on port #{@options[:port]}. " <<
359
- "You are currently running as '#{myself}'. Please re-run this program " <<
360
- "with root privileges with the following command:\n\n" <<
361
-
362
- " #{PlatformInfo.ruby_sudo_command} passenger start #{@original_args.join(' ')} --user=#{myself}\n\n" <<
363
-
364
- "Don't forget the '--user' part! That will make Phusion Passenger Standalone " <<
365
- "drop root privileges and switch to '#{myself}' after it has obtained " <<
366
- "port #{@options[:port]}."
367
- exit 1
368
- end
369
- end
370
- end
371
-
372
- if defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby"
373
- require 'java'
374
-
375
- def check_port(host_name, port)
376
- channel = java.nio.channels.SocketChannel.open
377
- begin
378
- address = java.net.InetSocketAddress.new(host_name, port)
379
- channel.configure_blocking(false)
380
- if channel.connect(address)
381
- return true
382
- end
383
-
384
- deadline = Time.now.to_f + 0.1
385
- done = false
386
- while true
387
- begin
388
- if channel.finish_connect
389
- return true
390
- end
391
- rescue java.net.ConnectException => e
392
- if e.message =~ /Connection refused/i
393
- return false
394
- else
395
- throw e
396
- end
397
- end
398
-
399
- # Not done connecting and no error.
400
- sleep 0.01
401
- if Time.now.to_f >= deadline
402
- return false
403
- end
404
- end
405
- ensure
406
- channel.close
407
- end
408
- end
409
- else
410
- def check_port_with_protocol(address, port, protocol)
411
- begin
412
- socket = Socket.new(protocol, Socket::Constants::SOCK_STREAM, 0)
413
- sockaddr = Socket.pack_sockaddr_in(port, address)
414
- begin
415
- socket.connect_nonblock(sockaddr)
416
- rescue Errno::ENOENT, Errno::EINPROGRESS, Errno::EAGAIN, Errno::EWOULDBLOCK
417
- if select(nil, [socket], nil, 0.1)
418
- begin
419
- socket.connect_nonblock(sockaddr)
420
- rescue Errno::EISCONN
421
- rescue Errno::EINVAL
422
- if PlatformInfo.os_name =~ /freebsd/i
423
- raise Errno::ECONNREFUSED
424
- else
425
- raise
426
- end
427
- end
428
- else
429
- raise Errno::ECONNREFUSED
430
- end
431
- end
432
- return true
433
- rescue Errno::ECONNREFUSED
434
- return false
435
- ensure
436
- socket.close if socket && !socket.closed?
437
- end
438
- end
439
-
440
- def check_port(address, port)
441
- begin
442
- check_port_with_protocol(address, port, Socket::Constants::AF_INET)
443
- rescue Errno::EAFNOSUPPORT
444
- check_port_with_protocol(address, port, Socket::Constants::AF_INET6)
445
- end
446
- end
447
- end
448
-
449
- def check_port_availability
450
- if !@options[:socket_file] && check_port(@options[:address], @options[:port])
451
- error "The address #{@options[:address]}:#{@options[:port]} is already " <<
452
- "in use by another process, perhaps another Phusion Passenger " <<
453
- "Standalone instance.\n\n" <<
454
- "If you want to run this Phusion Passenger Standalone instance on " <<
455
- "another port, use the -p option, like this:\n\n" <<
456
- " passenger start -p #{@options[:port] + 1}"
457
- exit 1
458
- end
459
- end
460
-
461
- def should_watch_logs?
462
- return !@options[:daemonize] && @options[:log_file] != "/dev/null"
463
- end
464
-
465
- def should_wait_until_nginx_has_exited?
466
- return !@options[:daemonize] || @app_finder.multi_mode?
467
- end
468
-
469
- # Returns the URL that Nginx will be listening on.
470
- def listen_url
471
- if @options[:socket_file]
472
- return @options[:socket_file]
473
- else
474
- if @options[:ssl] && !@options[:ssl_port]
475
- scheme = "https"
476
- else
477
- scheme = "http"
478
- end
479
- result = "#{scheme}://"
480
- if @options[:port] == 80
481
- result << @options[:address]
482
- else
483
- result << compose_ip_and_port(@options[:address], @options[:port])
484
- end
485
- result << "/"
486
- return result
487
- end
488
- end
489
-
490
- def ensure_runtime_installed
491
- @agent_exe = PhusionPassenger.find_support_binary(AGENT_EXE)
492
- if @options[:nginx_bin]
493
- @nginx_binary = @options[:nginx_bin]
494
- if !@nginx_binary
495
- abort "Error: Nginx binary #{@options[:nginx_bin]} does not exist"
496
- end
497
- if !@agent_exe
498
- install_runtime
499
- @agent_exe = PhusionPassenger.find_support_binary(AGENT_EXE)
500
- end
501
- else
502
- nginx_name = "nginx-#{@options[:nginx_version]}"
503
- @nginx_binary = PhusionPassenger.find_support_binary(nginx_name)
504
- if !@agent_exe || !@nginx_binary
505
- install_runtime
506
- @agent_exe = PhusionPassenger.find_support_binary(AGENT_EXE)
507
- @nginx_binary = PhusionPassenger.find_support_binary(nginx_name)
508
- end
509
- end
510
- end
511
-
512
- def install_runtime
513
- if @options[:dont_install_runtime]
514
- STDERR.puts "*** ERROR: Refusing to install the #{PROGRAM_NAME} Standalone runtime " +
515
- "because --no-install-runtime is given."
516
- abort
517
- end
518
-
519
- args = ["--brief", "--no-force-tip"]
520
- if @options[:binaries_url_root]
521
- args << "--url-root"
522
- args << @options[:binaries_url_root]
523
- end
524
- if @options[:nginx_version]
525
- args << "--nginx-version"
526
- args << @options[:nginx_version]
527
- end
528
- if @options[:nginx_tarball]
529
- args << "--nginx-tarball"
530
- args << @options[:nginx_tarball]
531
- end
532
- if @options[:dont_compile_runtime]
533
- args << "--no-compile"
534
- end
535
- PhusionPassenger.require_passenger_lib 'config/install_standalone_runtime_command'
536
- PhusionPassenger::Config::InstallStandaloneRuntimeCommand.new(args).run
537
- puts
538
- puts "--------------------------"
539
- puts
540
- end
541
-
542
- def set_stdout_stderr_binmode
543
- # We already set STDOUT and STDERR to binmode in bin/passenger, which
544
- # fixes https://github.com/phusion/passenger-ruby-heroku-demo/issues/11.
545
- # However RuntimeInstaller sets them to UTF-8, so here we set them back.
546
- STDOUT.binmode
547
- STDERR.binmode
548
- end
549
-
550
- def start_nginx
551
- begin
552
- @nginx.start
553
- rescue DaemonController::AlreadyStarted
554
- begin
555
- pid = @nginx.pid
556
- rescue SystemCallError, IOError
557
- pid = nil
558
- end
559
- if pid
560
- error "Phusion Passenger Standalone is already running on PID #{pid}."
561
- else
562
- error "Phusion Passenger Standalone is already running."
563
- end
564
- exit 1
565
- rescue DaemonController::StartError => e
566
- error "Could not start Passenger Nginx core:\n#{e}"
567
- exit 1
568
- end
569
- end
570
-
571
- def show_intro_message
572
- puts "=============== Phusion Passenger Standalone web server started ==============="
573
- puts "PID file: #{@options[:pid_file]}"
574
- puts "Log file: #{@options[:log_file]}"
575
- puts "Environment: #{@options[:environment]}"
576
- puts "Accessible via: #{listen_url}"
577
-
578
- puts
579
- if @options[:daemonize]
580
- puts "Serving in the background as a daemon."
581
- else
582
- puts "You can stop Phusion Passenger Standalone by pressing Ctrl-C."
583
- end
584
- puts "Problems? Check #{STANDALONE_DOC_URL}#troubleshooting"
585
- puts "==============================================================================="
586
- end
587
-
588
- def daemonize_without_fork
589
- STDERR.puts "Unable to daemonize using the current Ruby interpreter " +
590
- "(#{PlatformInfo.ruby_command}) because it does not support forking."
591
- exit 1
592
- end
593
-
594
- def daemonize
595
- pid = fork
596
- if pid
597
- # Parent
598
- exit!(0)
599
- else
600
- # Child
601
- trap "HUP", "IGNORE"
602
- STDIN.reopen("/dev/null", "r")
603
- STDOUT.reopen(@options[:log_file], "a")
604
- STDERR.reopen(@options[:log_file], "a")
605
- STDOUT.sync = true
606
- STDERR.sync = true
607
- Process.setsid
608
- end
609
- end
610
-
611
- # Wait until the termination pipe becomes readable (a hint for threads
612
- # to shut down), or until the timeout has been reached. Returns true if
613
- # the termination pipe became readable, false if the timeout has been reached.
614
- def wait_on_termination_pipe(timeout)
615
- ios = select([@termination_pipe[0]], nil, nil, timeout)
616
- return !ios.nil?
617
- end
618
-
619
- def watch_log_file(log_file)
620
- if File.exist?(log_file)
621
- backward = 0
622
- else
623
- # tail bails out if the file doesn't exist, so wait until it exists.
624
- while !File.exist?(log_file)
625
- sleep 1
626
- end
627
- backward = 10
628
- end
629
-
630
- IO.popen("tail -f -n #{backward} \"#{log_file}\"", "rb") do |f|
631
- begin
632
- while true
633
- begin
634
- line = f.readline
635
- @console_mutex.synchronize do
636
- STDOUT.write(line)
637
- STDOUT.flush
638
- end
639
- rescue EOFError
640
- break
641
- end
642
- end
643
- ensure
644
- Process.kill('TERM', f.pid) rescue nil
645
- end
646
- end
647
- end
648
-
649
- def watch_log_files_in_background
650
- @apps.each do |app|
651
- thread = Thread.new do
652
- watch_log_file("#{app[:root]}/log/#{@options[:environment]}.log")
653
- end
654
- @threads << thread
655
- @interruptable_threads << thread
656
- end
657
- thread = Thread.new do
658
- watch_log_file(@options[:log_file])
659
- end
660
- @threads << thread
661
- @interruptable_threads << thread
662
- end
663
-
664
- def touch_temp_dir_in_background
665
- result = system(@agent_exe,
666
- "temp-dir-toucher",
667
- @temp_dir,
668
- "--cleanup",
669
- "--daemonize",
670
- "--pid-file", "#{@temp_dir}/temp_dir_toucher.pid",
671
- "--log-file", @options[:log_file])
672
- if !result
673
- error "Cannot start #{@agent_exe} temp-dir-toucher"
674
- exit 1
675
- end
676
- end
677
-
678
- def begin_shutdown
679
- return if @shutting_down
680
- @shutting_down = 1
681
- trap("INT", &method(:signal_during_shutdown))
682
- trap("TERM", &method(:signal_during_shutdown))
683
- end
684
-
685
- def finalize_shutdown
686
- @shutting_down = nil
687
- trap("INT", "DEFAULT")
688
- trap("TERM", "DEFAULT")
689
- end
690
-
691
- def signal_during_shutdown(signal)
692
- if @shutting_down == 1
693
- @shutting_down += 1
694
- puts "Ignoring signal #{signal} during shutdown. Send it again to force exit."
695
- else
696
- exit!(1)
697
- end
698
- end
699
-
700
- def stop_touching_temp_dir_in_background
701
- if @toucher
702
- begin
703
- Process.kill('TERM', @toucher.pid)
704
- rescue Errno::ESRCH, Errno::ECHILD
705
- end
706
- @toucher.close
707
- end
708
- end
709
-
710
- def wait_until_nginx_has_exited
711
- # Since Nginx is not our child process (it daemonizes or we daemonize)
712
- # we cannot use Process.waitpid to wait for it. A busy-sleep-loop with
713
- # Process.kill(0, pid) isn't very efficient. Instead we do this:
714
- #
715
- # Connect to Nginx and wait until Nginx disconnects the socket because of
716
- # timeout. Keep doing this until we can no longer connect.
717
- while true
718
- if @options[:socket_file]
719
- socket = UNIXSocket.new(@options[:socket_file])
720
- else
721
- socket = TCPSocket.new(@options[:address], nginx_ping_port)
722
- end
723
- begin
724
- socket.read rescue nil
725
- ensure
726
- socket.close rescue nil
727
- end
728
- end
729
- rescue Errno::ECONNREFUSED, Errno::ECONNRESET
730
- end
731
-
732
- def stop_nginx
733
- @console_mutex.synchronize do
734
- STDOUT.write("Stopping web server...")
735
- STDOUT.flush
736
- @nginx.stop
737
- STDOUT.puts " done"
738
- STDOUT.flush
739
- end
740
- end
741
-
742
- def stop_threads
743
- if !@termination_pipe[1].closed?
744
- @termination_pipe[1].write("x")
745
- @termination_pipe[1].close
746
- end
747
- @interruptable_threads.each do |thread|
748
- thread.terminate
749
- end
750
- @interruptable_threads = []
751
- @threads.each do |thread|
752
- thread.join
753
- end
754
- @threads = []
755
- end
756
-
757
- #### Config file template helpers ####
758
-
759
- def nginx_listen_address(options = @options, for_ping_port = false)
760
- if options[:socket_file]
761
- return "unix:" + File.absolute_path_no_resolve(options[:socket_file])
762
- else
763
- if for_ping_port
764
- port = options[:ping_port]
765
- else
766
- port = options[:port]
767
- end
768
- return compose_ip_and_port(options[:address], port)
769
- end
770
- end
771
-
772
- def nginx_listen_address_with_ssl_port(options = @options)
773
- if options[:socket_file]
774
- return "unix:" + File.absolute_path_no_resolve(options[:socket_file])
775
- else
776
- return compose_ip_and_port(options[:address], options[:ssl_port])
777
- end
778
- end
779
-
780
- def compose_ip_and_port(ip, port)
781
- if ip =~ /:/
782
- # IPv6
783
- return "[#{ip}]:#{port}"
784
- else
785
- return "#{ip}:#{port}"
786
- end
787
- end
788
-
789
- def default_group_for(username)
790
- user = Etc.getpwnam(username)
791
- group = Etc.getgrgid(user.gid)
792
- return group.name
793
- end
794
-
795
- #################
796
- end
797
-
798
- end # module Standalone
799
- end # module PhusionPassenger