Allow stderr_path and stdout_path to be set in the config
[unicorn.git] / bin / unicorn
blob18edf43820ff893e8ee1791dbc44d1e8f5e8b6b8
1 #!/home/ew/bin/ruby
2 $stdin.sync = $stdout.sync = $stderr.sync = true
3 require 'unicorn' # require this first to populate Unicorn::DEFAULT_START_CTX
4 require 'rack'
5 require 'optparse'
7 env = "development"
8 daemonize = false
9 listeners = []
10 options = { :listeners => listeners }
11 host = Unicorn::Const::DEFAULT_HOST
12 port = Unicorn::Const::DEFAULT_PORT
14 opts = OptionParser.new("", 24, ' ') do |opts|
15 opts.banner = "Usage: #{File.basename($0)} " \
16 "[ruby options] [unicorn options] [rackup config file]"
18 opts.separator "Ruby options:"
20 lineno = 1
21 opts.on("-e", "--eval LINE", "evaluate a LINE of code") do |line|
22 eval line, TOPLEVEL_BINDING, "-e", lineno
23 lineno += 1
24 end
26 opts.on("-d", "--debug", "set debugging flags (set $DEBUG to true)") do
27 $DEBUG = true
28 end
30 opts.on("-w", "--warn", "turn warnings on for your script") do
31 $-w = true
32 end
34 opts.on("-I", "--include PATH",
35 "specify $LOAD_PATH (may be used more than once)") do |path|
36 $LOAD_PATH.unshift(*path.split(/:/))
37 end
39 opts.on("-r", "--require LIBRARY",
40 "require the library, before executing your script") do |library|
41 require library
42 end
44 opts.separator "Unicorn options:"
46 # some of these switches exist for rackup command-line compatibility,
48 opts.on("-o", "--host HOST",
49 "listen on HOST (default: #{Unicorn::Const::DEFAULT_HOST})") do |h|
50 host = h
51 end
53 opts.on("-p", "--port PORT",
54 "use PORT (default: #{Unicorn::Const::DEFAULT_PORT})") do |p|
55 port = p.to_i
56 end
58 opts.on("-E", "--env ENVIRONMENT",
59 "use ENVIRONMENT for defaults (default: development)") do |e|
60 env = e
61 end
63 opts.on("-D", "--daemonize", "run daemonized in the background") do |d|
64 daemonize = d ? true : false
65 end
67 # Unicorn-specific stuff
68 opts.on("-l", "--listen {HOST:PORT|PATH}",
69 "listen on HOST:PORT or PATH",
70 "this may be specified multiple times",
71 "(default: #{Unicorn::Const::DEFAULT_LISTEN})") do |address|
72 listeners << address
73 end
75 opts.on("-C", "--directory PATH", "run in this directory") do |d|
76 options[:directory] = d
77 end
79 opts.on("-c", "--config-file FILE", "Unicorn-specific config file") do |f|
80 options[:config_file] = File.expand_path(f)
81 end
83 # I'm avoiding Unicorn-specific config options on the command-line.
84 # IMNSHO, config options on the command-line are redundant given
85 # config files and make things unnecessarily complicated with multiple
86 # places to look for a config option.
88 opts.separator "Common options:"
90 opts.on_tail("-h", "--help", "Show this message") do
91 puts opts
92 exit
93 end
95 opts.on_tail("-v", "--version", "Show version") do
96 puts "unicorn v#{Unicorn::Const::UNICORN_VERSION}"
97 exit
98 end
100 opts.parse! ARGV
103 require 'pp' if $DEBUG
105 config = ARGV[0] || "config.ru"
106 abort "configuration file #{config} not found" unless File.exist?(config)
108 inner_app = case config
109 when /\.ru$/
110 raw = File.open(config, "rb") { |fp| fp.sysread(fp.stat.size) }
111 if raw[/^#\\(.*)/]
112 warn %(not parsing embedded command-line options: "#$1")
114 lambda { || eval("Rack::Builder.new {(#{raw}\n)}.to_app", nil, config) }
115 else
116 lambda do ||
117 require config
118 Object.const_get(File.basename(config, '.rb').capitalize)
122 app = case env
123 when "development"
124 lambda do ||
125 Rack::Builder.new do
126 use Rack::CommonLogger, $stderr
127 use Rack::ShowExceptions
128 use Rack::Lint
129 run inner_app.call
130 end.to_app
132 when "deployment"
133 lambda do ||
134 Rack::Builder.new do
135 use Rack::CommonLogger, $stderr
136 run inner_app.call
137 end.to_app
139 else
140 inner_app
143 if listeners.empty?
144 listener = "#{host}:#{port}"
145 listeners << listener if listener != Unicorn::Const::DEFAULT_LISTEN
148 if $DEBUG
149 pp({
150 :unicorn_options => options,
151 :app => app,
152 :inner_app => inner_app,
153 :daemonize => daemonize,
157 # only daemonize if we're not inheriting file descriptors from our parent
158 if daemonize
160 $stdin.reopen("/dev/null")
161 unless ENV['UNICORN_FD']
162 exit if fork
163 Process.setsid
164 exit if fork
167 # We don't do a lot of standard daemonization stuff:
168 # * $stderr/$stderr can/will be redirected separately
169 # * umask is whatever was set by the parent process at startup
170 # and can be set in config.ru and config_file, so making it
171 # 0000 and potentially exposing sensitive log data can be bad
172 # policy.
173 # * Don't bother to chdir here since Unicorn is designed to
174 # run inside APP_ROOT (or whatever the "directory" directive
175 # specifies). Unicorn will also re-chdir() to the directory
176 # it was started in when being re-executed to pickup code
177 # changes if the original deployment directory is a symlink
178 # or otherwise got replaced.
181 Unicorn.run(app, options)