# File lib/phusion_passenger/utils.rb, line 194 def prepare_app_process(startup_file, options) options["app_root"] = canonicalize_path(options["app_root"]) Dir.chdir(options["app_root"]) lower_privilege(startup_file, options) path, is_parent = check_directory_tree_permissions(options["app_root"]) if path username = Etc.getpwuid(Process.euid).name groupname = Etc.getgrgid(Process.egid).name message = "This application process is currently running as " + "user '#{username}' and group '#{groupname}' and must be " + "able to access its application root directory " + "'#{options["app_root"]}'. " if is_parent message << "However the parent directory '#{path}' " + "has wrong permissions, thereby preventing " + "this process from accessing its application " + "root directory. Please fix the permissions " + "of the directory '#{path}' first." else message << "However this directory is not accessible " + "because it has wrong permissions. Please fix " + "these permissions first." end raise(message) end ENV["RAILS_ENV"] = ENV["RACK_ENV"] = options["environment"] base_uri = options["base_uri"] if base_uri && !base_uri.empty? && base_uri != "/" ENV["RAILS_RELATIVE_URL_ROOT"] = base_uri ENV["RACK_BASE_URI"] = base_uri end encoded_environment_variables = options["environment_variables"] if encoded_environment_variables env_vars_string = encoded_environment_variables.unpack("m").first env_vars_array = env_vars_string.split("\0", -1) env_vars_array.pop env_vars = Hash[*env_vars_array] env_vars.each_pair do |key, value| ENV[key] = value end end # Instantiate the analytics logger if requested. Can be nil. require 'phusion_passenger/analytics_logger' options["analytics_logger"] = AnalyticsLogger.new_from_options(options) # Make sure RubyGems uses any new environment variable values # that have been set now (e.g. $HOME, $GEM_HOME, etc) and that # it is able to detect newly installed gems. Gem.clear_paths # Because spawned app processes exit using #exit!, #at_exit # blocks aren't called. Here we ninja patch Kernel so that # we can call #at_exit blocks during app process shutdown. class << Kernel def passenger_call_at_exit_blocks @passenger_at_exit_blocks ||= [] @passenger_at_exit_blocks.reverse_each do |block| block.call end end def passenger_at_exit(&block) @passenger_at_exit_blocks ||= [] @passenger_at_exit_blocks << block return block end end Kernel.class_eval do def at_exit(&block) return Kernel.passenger_at_exit(&block) end end # Rack::ApplicationSpawner depends on the 'rack' library, but the app # might want us to use a bundled version instead of a # gem/apt-get/yum/whatever-installed version. Therefore we must setup # the correct load paths before requiring 'rack'. # # The most popular tool for bundling dependencies is Bundler. Bundler # works as follows: # - If the bundle is locked then a file .bundle/environment.rb exists # which will setup the load paths. # - If the bundle is not locked then the load paths must be set up by # calling Bundler.setup. # - Rails 3's boot.rb automatically loads .bundle/environment.rb or # calls Bundler.setup if that's not available. # - Other Rack apps might not have a boot.rb but we still want to setup # Bundler. # - Some Rails 2 apps might have explicitly added Bundler support. # These apps call Bundler.setup in their preinitializer.rb. # # So the strategy is as follows: # Our strategy might be completely unsuitable for the app or the # developer is using something other than Bundler, so we let the user # manually specify a load path setup file. if options["load_path_setup_file"] require File.expand_path(options["load_path_setup_file"]) # The app developer may also override our strategy with this magic file. elsif File.exist?('config/setup_load_paths.rb') require File.expand_path('config/setup_load_paths') # If the Bundler lock environment file exists then load that. If it # exists then there's a 99.9% chance that loading it is the correct # thing to do. elsif File.exist?('.bundle/environment.rb') require File.expand_path('.bundle/environment') # If the Bundler environment file doesn't exist then there are two # possibilities: # 1. Bundler is not used, in which case we don't have to do anything. # 2. Bundler *is* used, but the gems are not locked and we're supposed # to call Bundler.setup. # # The existence of Gemfile indicates whether (2) is true: elsif File.exist?('Gemfile') # In case of Rails 3, config/boot.rb already calls Bundler.setup. # However older versions of Rails may not so loading boot.rb might # not be the correct thing to do. To be on the safe side we # call Bundler.setup ourselves; calling Bundler.setup twice is # harmless. If this isn't the correct thing to do after all then # there's always the load_path_setup_file option and # setup_load_paths.rb. require 'rubygems' require 'bundler' Bundler.setup end # Bundler might remove Phusion Passenger from the load path in its zealous # attempt to un-require RubyGems, so here we put Phusion Passenger back # into the load path. This must be done before loading the app's startup # file because the app might require() Phusion Passenger files. if !$LOAD_PATH.include?(LIBDIR) $LOAD_PATH.unshift(LIBDIR) $LOAD_PATH.uniq! end # !!! NOTE !!! # If the app is using Bundler then any dependencies required past this # point must be specified in the Gemfile. Like ruby-debug if debugging is on... PhusionPassenger._spawn_options = options end