require 'rubygems' require 'set' module Cluster::ExecBase @@light_cluster_initialized = false alias :original_start :start def start read_options if @options['disable_mongrel_light_cluster'] || ENV['DISABLE_MONGREL_LIGHT_CLUSTER'] return original_start end init_light_cluster gem 'mongrel' argv = [] argv << "start" argv << "-d" argv << "-e" << @options["environment"].to_s if @options["environment"] argv << "-a" << @options["address"].to_s if @options["address"] argv << "-c" << @options["cwd"].to_s if @options["cwd"] argv << "-t" << @options["timeout"].to_s if @options["timeout"] argv << "-m" << @options["mime_map"].to_s if @options["mime_map"] argv << "-r" << @options["docroot"].to_s if @options["docroot"] argv << "-n" << @options["num_procs"].to_s if @options["num_procs"] argv << "-B" if @options["debug"] argv << "-S" << @options["config_script"].to_s if @options["config_script"] argv << "--user" << @options["user"].to_s if @options["user"] argv << "--group" << @options["group"].to_s if @options["group"] argv << "--prefix" << @options["prefix"].to_s if @options["prefix"] # Garbage collect stuff now so that they don't get collected # in the child processes (which will make pages dirty). ObjectSpace.garbage_collect @ports.each do |port| if @clean && pid_file_exists?(port) && !check_process(port) pid_file = port_pid_file(port) log "missing process: removing #{pid_file}" File.unlink(pid_file) end if pid_file_exists?(port) && check_process(port) log "already started port #{port}" next end instance_argv = argv.dup instance_argv << "-p" << port.to_s instance_argv << "-P" << port_pid_file(port) instance_argv << "-l" << port_log_file(port) log "starting port #{port}" log_verbose "mongrel_rails " + instance_argv.join(' ') exit_status, output = run_ruby_script('mongrel_rails', instance_argv) log_error output unless exit_status.success? end end private def init_light_cluster return if @@light_cluster_initialized ENV['RAILS_ENV'] = @options['environment'] if @options['environment'] preload_rails preload_app @@light_cluster_initialized = true end def preload_rails return if defined?(RAILS_ROOT) rails_root = @options['cwd'] || ENV['RAILS_ROOT'] || Dir.pwd log_verbose "Preloading Ruby on Rails" require "#{rails_root}/config/environment" require 'ruby_version_check' require 'initializer' require 'dispatcher' require 'breakpoint' if defined?(BREAKPOINT_SERVER_PORT) Dir.chdir(RAILS_ROOT) end def preload_app return if defined?(ApplicationController) preload_files = [] include_files = glob(@options['preload'] || ['app/**/*.rb', 'lib/**/*.rb', 'vendor/plugins/*/init.rb']) exclude_files = Set.new(glob(@options['dont_preload'] || '')) include_files.each do |file| if !exclude_files.include?(file) && file != "app/controllers/application.rb" preload_files << file end end log_verbose 'Preloading application.rb' require 'application.rb' preload_files.each do |file| log_verbose "Preloading #{file}" expanded = File.expand_path("#{RAILS_ROOT}/#{file}").sub!(/\.rb$/, '') require expanded end end def glob(option) if option.is_a?(Array) result = [] option.each do |pattern| result << Dir.glob(pattern) end return result.flatten! else return Dir.glob(option.to_s) end end def run_ruby_script(script, argv) reader, writer = IO.pipe pid = fork do ARGV.clear ARGV << argv ARGV.flatten! reader.close begin STDIN.reopen('/dev/null', 'r'); rescue; end begin STDOUT.reopen(writer); rescue; end begin STDERR.reopen(STDOUT); rescue; end load script exit end writer.close Process.waitpid(pid) output = reader.read reader.close return $?, output end end