about summary refs log tree commit homepage
path: root/bin
diff options
context:
space:
mode:
Diffstat (limited to 'bin')
-rwxr-xr-xbin/unicorn87
-rwxr-xr-xbin/unicorn_rails202
2 files changed, 232 insertions, 57 deletions
diff --git a/bin/unicorn b/bin/unicorn
index ebf57c3..a34d9bc 100755
--- a/bin/unicorn
+++ b/bin/unicorn
@@ -1,14 +1,13 @@
 #!/home/ew/bin/ruby
-$stdin.sync = $stdout.sync = $stderr.sync = true
-require 'unicorn' # require this first to populate Unicorn::DEFAULT_START_CTX
+require 'unicorn/launcher'
 require 'optparse'
 
 env = "development"
 daemonize = false
 listeners = []
 options = { :listeners => listeners }
-host = Unicorn::Const::DEFAULT_HOST
-port = Unicorn::Const::DEFAULT_PORT
+host, port = Unicorn::Const::DEFAULT_HOST, Unicorn::Const::DEFAULT_PORT
+set_listener = false
 
 opts = OptionParser.new("", 24, '  ') do |opts|
   opts.banner = "Usage: #{File.basename($0)} " \
@@ -47,11 +46,13 @@ opts = OptionParser.new("", 24, '  ') do |opts|
   opts.on("-o", "--host HOST",
           "listen on HOST (default: #{Unicorn::Const::DEFAULT_HOST})") do |h|
     host = h
+    set_listener = true
   end
 
   opts.on("-p", "--port PORT",
           "use PORT (default: #{Unicorn::Const::DEFAULT_PORT})") do |p|
     port = p.to_i
+    set_listener = true
   end
 
   opts.on("-E", "--env ENVIRONMENT",
@@ -104,86 +105,58 @@ opts = OptionParser.new("", 24, '  ') do |opts|
   opts.parse! ARGV
 end
 
-require 'pp' if $DEBUG
-
-# require Rack as late as possible in case $LOAD_PATH is modified
-# in config.ru or command-line
-require 'rack'
-
 config = ARGV[0] || "config.ru"
 abort "configuration file #{config} not found" unless File.exist?(config)
 
-inner_app = case config
-when /\.ru$/
-  raw = File.open(config, "rb") { |fp| fp.sysread(fp.stat.size) }
+if config =~ /\.ru$/
   # parse embedded command-line options in config.ru comments
-  if raw[/^#\\(.*)/]
+  if File.open(config, "rb") { |fp| fp.sysread(fp.stat.size) } =~ /^#\\(.*)/
     opts.parse! $1.split(/\s+/)
   end
-  lambda { || eval("Rack::Builder.new {(#{raw}\n)}.to_app", nil, config) }
-else
-  lambda do ||
+end
+
+require 'pp' if $DEBUG
+
+app = lambda do ||
+  # require Rack as late as possible in case $LOAD_PATH is modified
+  # in config.ru or command-line
+  require 'rack'
+  inner_app = case config
+  when /\.ru$/
+    raw = File.open(config, "rb") { |fp| fp.sysread(fp.stat.size) }
+    eval("Rack::Builder.new {(#{raw}\n)}.to_app", nil, config)
+  else
     require config
     Object.const_get(File.basename(config, '.rb').capitalize)
   end
-end
-
-app = case env
-when "development"
-  lambda do ||
+  pp({ :inner_app => inner_app }) if $DEBUG
+  case env
+  when "development"
     Rack::Builder.new do
       use Rack::CommonLogger, $stderr
       use Rack::ShowExceptions
       use Rack::Lint
-      run inner_app.call
+      run inner_app
     end.to_app
-  end
-when "deployment"
-  lambda do ||
+  when "deployment"
     Rack::Builder.new do
       use Rack::CommonLogger, $stderr
-      run inner_app.call
+      run inner_app
     end.to_app
+  else
+    inner_app
   end
-else
-  inner_app
 end
 
-if listeners.empty?
-  listener = "#{host}:#{port}"
-  listeners << listener
-end
+listeners << "#{host}:#{port}" if set_listener
 
 if $DEBUG
   pp({
     :unicorn_options => options,
     :app => app,
-    :inner_app => inner_app,
     :daemonize => daemonize,
   })
 end
 
-# only daemonize if we're not inheriting file descriptors from our parent
-if daemonize
-
-  $stdin.reopen("/dev/null")
-  unless ENV['UNICORN_FD']
-    exit if fork
-    Process.setsid
-    exit if fork
-  end
-
-  # We don't do a lot of standard daemonization stuff:
-  #   * $stderr/$stderr can/will be redirected separately
-  #   * umask is whatever was set by the parent process at startup
-  #     and can be set in config.ru and config_file, so making it
-  #     0000 and potentially exposing sensitive log data can be bad
-  #     policy.
-  #   * Don't bother to chdir here since Unicorn is designed to
-  #     run inside APP_ROOT.  Unicorn will also re-chdir() to
-  #     the directory it was started in when being re-executed
-  #     to pickup code changes if the original deployment directory
-  #     is a symlink or otherwise got replaced.
-end
-
+Unicorn::Launcher.daemonize! if daemonize
 Unicorn.run(app, options)
diff --git a/bin/unicorn_rails b/bin/unicorn_rails
new file mode 100755
index 0000000..b3fda7b
--- /dev/null
+++ b/bin/unicorn_rails
@@ -0,0 +1,202 @@
+#!/home/ew/bin/ruby
+require 'unicorn/launcher'
+require 'optparse'
+require 'fileutils'
+
+rails_pid = "#{Unicorn::HttpServer::START_CTX[:cwd]}/tmp/pids/unicorn.pid"
+cmd = File.basename($0)
+daemonize = false
+listeners = []
+options = { :listeners => listeners }
+host, port = Unicorn::Const::DEFAULT_HOST, Unicorn::Const::DEFAULT_PORT
+set_listener = false
+ENV['RAILS_ENV'] ||= "development"
+map_path = ENV['RAILS_RELATIVE_URL_ROOT']
+
+opts = OptionParser.new("", 24, '  ') do |opts|
+  opts.banner = "Usage: #{cmd} " \
+                "[ruby options] [#{cmd} options] [rackup config file]"
+  opts.separator "Ruby options:"
+
+  lineno = 1
+  opts.on("-e", "--eval LINE", "evaluate a LINE of code") do |line|
+    eval line, TOPLEVEL_BINDING, "-e", lineno
+    lineno += 1
+  end
+
+  opts.on("-d", "--debug", "set debugging flags (set $DEBUG to true)") do
+    $DEBUG = true
+  end
+
+  opts.on("-w", "--warn", "turn warnings on for your script") do
+    $-w = true
+  end
+
+  opts.on("-I", "--include PATH",
+          "specify $LOAD_PATH (may be used more than once)") do |path|
+    $LOAD_PATH.unshift(*path.split(/:/))
+  end
+
+  opts.on("-r", "--require LIBRARY",
+          "require the library, before executing your script") do |library|
+    require library
+  end
+
+  opts.separator "#{cmd} options:"
+
+  # some of these switches exist for rackup command-line compatibility,
+
+  opts.on("-o", "--host HOST",
+          "listen on HOST (default: #{Unicorn::Const::DEFAULT_HOST})") do |h|
+    host = h
+    set_listener = true
+  end
+
+  opts.on("-p", "--port PORT", "use PORT (default: #{port})") do |p|
+    port = p.to_i
+    set_listener = true
+  end
+
+  opts.on("-E", "--env ENVIRONMENT",
+          "use ENVIRONMENT for defaults (default: development)") do |e|
+    ENV['RAILS_ENV'] = e
+  end
+
+  opts.on("-D", "--daemonize", "run daemonized in the background") do |d|
+    daemonize = d ? true : false
+  end
+
+  # Unicorn-specific stuff
+  opts.on("-l", "--listen {HOST:PORT|PATH}",
+          "listen on HOST:PORT or PATH",
+          "this may be specified multiple times",
+          "(default: #{Unicorn::Const::DEFAULT_LISTEN})") do |address|
+    listeners << address
+  end
+
+  opts.on("-c", "--config-file FILE", "Unicorn-specific config file") do |f|
+    options[:config_file] = File.expand_path(f)
+  end
+
+  opts.on("-P", "--path PATH", "Runs Rails app mounted at a specific path.",
+          "(default: /") do |v|
+    ENV['RAILS_RELATIVE_URL_ROOT'] = map_path = v
+  end
+
+  # I'm avoiding Unicorn-specific config options on the command-line.
+  # IMNSHO, config options on the command-line are redundant given
+  # config files and make things unnecessarily complicated with multiple
+  # places to look for a config option.
+
+  opts.separator "Common options:"
+
+  opts.on_tail("-h", "--help", "Show this message") do
+    puts opts
+    exit
+  end
+
+  opts.on_tail("-v", "--version", "Show version") do
+    puts " v#{Unicorn::Const::UNICORN_VERSION}"
+    exit
+  end
+
+  opts.parse! ARGV
+end
+
+config = ARGV[0] || (File.exist?('config.ru') ? 'config.ru' : nil)
+
+if config && config =~ /\.ru$/
+  # parse embedded command-line options in config.ru comments
+  if File.open(config, "rb") { |fp| fp.sysread(fp.stat.size) } =~ /^#\\(.*)/
+    opts.parse! $1.split(/\s+/)
+  end
+end
+
+require 'pp' if $DEBUG
+
+# this won't run until after forking if preload_app is false
+app = lambda do ||
+  # Load Rails and the private version of Rack it bundles.
+  begin
+    require 'config/boot'
+  rescue LoadError => err
+    abort "#$0 must be run inside RAILS_ROOT: #{err.inspect}"
+  end
+  defined?(::RAILS_ROOT) or abort "RAILS_ROOT not defined by config/boot"
+  defined?(::RAILS_ENV) or abort "RAILS_ENV not defined by config/boot"
+  defined?(::Rails::VERSION::STRING) or
+    abort "Rails::VERSION::STRING not defined by config/boot"
+
+  inner_app = case config
+  when nil
+    require 'config/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
+
+    if old_rails
+      require 'rack'
+      require 'unicorn/app/old_rails'
+      Unicorn::App::OldRails.new
+    else
+      ActionController::Dispatcher.new
+    end
+  when /\.ru$/
+    raw = File.open(config, "rb") { |fp| fp.sysread(fp.stat.size) }
+    eval("Rack::Builder.new {(#{raw}\n)}.to_app", nil, config)
+  else
+    require config
+    Object.const_get(File.basename(config, '.rb').capitalize)
+  end
+
+  map_path ||= '/'
+  Rack::Builder.new do
+    if inner_app.class.to_s == "Unicorn::App::OldRails"
+      if map_path != '/'
+        # patches + tests welcome, but I really cbf to deal with this
+        # since all apps I've ever dealt with just use "/" ...
+        $stderr.puts "relative URL roots may not work for older Rails"
+      end
+      $stderr.puts "LogTailer not available for Rails < 2.3" unless daemonize
+      $stderr.puts "Debugger not available" if $DEBUG
+      map(map_path) do
+        require 'unicorn/app/old_rails/static'
+        use Unicorn::App::OldRails::Static
+        run inner_app
+      end
+    else
+      use Rails::Rack::LogTailer unless daemonize
+      use Rails::Rack::Debugger if $DEBUG
+      map(map_path) do
+        use Rails::Rack::Static
+        run inner_app
+      end
+    end
+  end.to_app
+end
+
+listeners << "#{host}:#{port}" if set_listener
+
+if $DEBUG
+  pp({
+    :unicorn_options => options,
+    :app => app,
+    :daemonize => daemonize,
+  })
+end
+
+# ensure Rails standard tmp paths exist
+%w(cache pids sessions sockets).each do |dir|
+  FileUtils.mkdir_p("tmp/#{dir}")
+end
+
+if daemonize
+  options[:pid] = rails_pid
+  Unicorn::Launcher.daemonize!
+end
+Unicorn.run(app, options)