lib/golden_brindle/start.rb in golden_brindle-0.1.1 vs lib/golden_brindle/start.rb in golden_brindle-0.2

- old
+ new

@@ -1,10 +1,10 @@ - module Brindle class Start < GemPlugin::Plugin "/commands" include GoldenBrindle::Command::Base + include Hooks def configure options [ ["-e", "--environment ENV", "Rails environment to run as", :@environment, ENV['RAILS_ENV'] || "development"], ["-b", "--bundler", "Use bundler to start unicorn instances", :@bundler, false], @@ -26,84 +26,11 @@ ['', '--group GROUP', "Group to run as", :@group, nil], ['', '--prefix PATH', "URL prefix for Rails app", :@prefix, nil] ] end - - # - # Rails 3 dispatcher support - # Code from unicorn_rails script - # - def self.rails_dispatcher - if ::Rails::VERSION::MAJOR >= 3 && ::File.exist?('config/application.rb') - if ::File.read('config/application.rb') =~ /^module\s+([\w:]+)\s*$/ - app_module = Object.const_get($1) - begin - result = app_module::Application - rescue NameError - end - end - end - - if result.nil? && defined?(ActionController::Dispatcher) - result = ActionController::Dispatcher.new - end - - result || abort("Unable to locate the application dispatcher class") - end - - def rails_builder(daemonize) - # this lambda won't run until after forking if preload_app is false - lambda do || - # Load Rails - begin - require ::File.expand_path('config/boot') - require ::File.expand_path('config/environment') - rescue LoadError => err - abort "#$0 must be run inside RAILS_ROOT: #{err.inspect}" - end - - defined?(::Rails::VERSION::STRING) or - abort "Rails::VERSION::STRING not defined by config/{boot,environment}" - # it seems Rails >=2.2 support Rack, but only >=2.3 requires it - old_rails = case ::Rails::VERSION::MAJOR - when 0, 1 then true - when 2 then Rails::VERSION::MINOR < 3 ? true : false - else - false - end - - Rack::Builder.new do - map_path = ENV['RAILS_RELATIVE_URL_ROOT'] || '/' - if old_rails - if map_path != '/' - # patches + tests welcome, but I really cbf to deal with this - # since all apps I've ever dealt with just use "/" ... - warn "relative URL roots may not work for older Rails" - end - warn "LogTailer not available for Rails < 2.3" unless daemonize - warn "Debugger not available" if $DEBUG - require 'unicorn/app/old_rails' - map(map_path) do - use Unicorn::App::OldRails::Static - run Unicorn::App::OldRails.new - end - else - use Rails::Rack::LogTailer unless daemonize - use Rails::Rack::Debugger if $DEBUG - map(map_path) do - unless defined?(ActionDispatch::Static) - use Rails::Rack::Static - end - run Brindle::Start.rails_dispatcher - end - end - end.to_app - end - end - - def validate + def validate if @config_file valid_exists?(@config_file, "Config file not there: #@config_file") return false unless @valid @config_file = File.expand_path(@config_file) load_config @@ -125,105 +52,73 @@ valid?(@prefix[0] == ?/ && @prefix[-1] != ?/, "Prefix must begin with / and not end in /") if @prefix valid_dir? File.dirname(File.join(@cwd,@log_file)), "Path to log file not valid: #{@log_file}" valid_dir? File.dirname(File.join(@cwd,@pid_file)), "Path to pid file not valid: #{@pid_file}" valid_user? @user if @user valid_group? @group if @group - return @valid + @valid end + + def default_options + { + :listeners => [], + :pid => @pid_file, + :config_file => @config_script, + :worker_processes => @workers.to_i, + :working_directory => @cwd, + :timeout => @timeout.to_i + } + end + + def bundler_cmd + cmd = "bundle exec #{@opt.program_name}" + @original_args.each_slice(2) do |arg_key,value| + cmd << " #{arg_key} #{value}" if arg_key != "-b" + end + cmd + end + + def collect_listeners + return if @port.nil? + start_port = end_port = nil + start_port ||= @port.to_i + end_port ||= start_port + @servers.to_i - 1 + (start_port..end_port).map do |port| + "#{@address}:#{port}" + end + end + + def parse_listen_option + return if @listen.nil? || @listen.empty? + @listen.split(',').map do |listen| + listen = File.join(@cwd,listen) if listen[0..0] != "/" && !listen.match(/\w+\:\w+/) + "#{listen}" + end + end def run # Change there to start, then we'll have to come back after daemonize Dir.chdir(@cwd) if @bundler puts "Using Bundler" puts "reexec via bundle exec" - require 'pp' - cmd_for_exec = "bundle exec #{@opt.program_name}" - @original_args.each_slice(2) do |arg_key,value| - cmd_for_exec << " #{arg_key} #{value}" if arg_key != "-b" - end - exec(cmd_for_exec) + exec(bundler_cmd) end - options = { - :listeners => [], - :pid => @pid_file, - :config_file => @config_script, - :worker_processes => @workers.to_i, - :working_directory => @cwd, - :timeout => @timeout.to_i - } + options = default_options # set user via Unicorn options. If we don't set group - then use only user options[:user] = @user unless @user.nil? options[:stderr_path] = options[:stdout_path] = @log_file if @daemon - # ensure Rails standard tmp paths exist - options[:after_reload] = lambda do - FileUtils.mkdir_p(%w(cache pids sessions sockets).map! { |d| "tmp/#{d}" }) - end - options[:preload_app] = @preload - # do base steps for Rails - options[:after_fork] = lambda do |server, worker| - defined?(ActiveRecord::Base) and - ActiveRecord::Base.establish_connection - # trying to change user and group - begin - # check if something not set in config or cli - unless @user.nil? || @group.nil? - uid, gid = Process.euid, Process.egid - user, group = @user, @group - target_uid = Etc.getpwnam(user).uid - target_gid = Etc.getgrnam(group).gid - worker.tmp.chown(target_uid, target_gid) - if uid != target_uid || gid != target_gid - Process.initgroups(user, target_gid) - Process::GID.change_privilege(target_gid) - Process::UID.change_privilege(target_uid) - end - end - rescue => e - if ENV['RAILS_ENV'] == 'development' - STDERR.puts "couldn't change user, oh well" - else - raise e - end - end - end - options[:before_fork] = lambda do |server, worker| - defined?(ActiveRecord::Base) and - ActiveRecord::Base.connection.disconnect! - # http://rubyenterpriseedition.com/faq.html#adapt_apps_for_cow - if GC.respond_to?(:copy_on_write_friendly=) - GC.copy_on_write_friendly = true - end - old_pid = "#{server.config[:pid]}.oldbin" - if File.exists?(old_pid) && server.pid != old_pid - begin - Process.kill("QUIT", File.read(old_pid).to_i) - rescue Errno::ENOENT, Errno::ESRCH - end - end - end + options.merge!(collect_hooks) ENV['RAILS_ENV'] = @environment ENV['RAILS_RELATIVE_URL_ROOT'] = @prefix - unless @port.nil? - start_port = end_port = nil - start_port ||= @port.to_i - end_port ||= start_port + @servers.to_i - 1 - (start_port..end_port).each do |port| - options[:listeners] << "#{@address}:#{port}" - end + [collect_listeners, parse_listen_option].each do |listeners| + options[:listeners] += listeners if listeners end - unless @listen.nil? || @listen.empty? - @listen.split(',').each do |listen| - listen = File.join(@cwd,listen) if listen[0..0] != "/" && !listen.match(/\w+\:\w+/) - options[:listeners] << "#{listen}" - end - end - app = rails_builder(@daemon) + app = RailsSupport.rails_builder(@daemon) if @daemon Unicorn::Launcher.daemonize!(options) end - puts "start Unicorn..." + puts "start Unicorn v#{Unicorn::Const::UNICORN_VERSION}..." if Unicorn.respond_to?(:run) Unicorn.run(app, options) else Unicorn::HttpServer.new(app, options).start.join end