4 unless respond_to? :daemonize # Already part of Ruby 1.9, yeah!
5 # Turns the current script into a daemon process that detaches from the console.
6 # It can be shut down with a TERM signal. Taken from ActiveSupport.
8 exit if fork # Parent exits, child continues.
9 Process.setsid # Become session leader.
10 exit if fork # Zap session leader. See [1].
11 Dir.chdir "/" # Release old working directory.
12 File.umask 0000 # Ensure sensible umask. Adjust as needed.
13 STDIN.reopen "/dev/null" # Free file descriptors and
14 STDOUT.reopen "/dev/null", "a" # point them somewhere sensible.
15 STDERR.reopen STDOUT # STDOUT/ERR should better go to a logfile.
23 # Classes are modules and I hate this 'Base' class pattern. I'm putting
24 # other classes inside this one.
25 autoload :Rails, LIBDIR + '/ebb/runner/rails'
27 # Kill the process which PID is stored in +pid_file+.
28 def self.kill(pid_file, timeout=60)
29 raise ArgumentError, 'You must specify a pid_file to stop deamonized server' unless pid_file
31 if pid = File.read(pid_file)
34 Process.kill('KILL', pid)
35 Ebb.log.puts "stopped!"
37 Ebb.log.puts "Can't stop process, no PID found in #{@pid_file}"
39 rescue Errno::ESRCH # No such process
40 Ebb.log.puts "process not found!"
42 File.delete(pid_file) rescue nil
45 def self.remove_pid_file(file)
46 File.delete(file) if file && File.exists?(file) && Process.pid == File.read(file)
49 def self.write_pid_file(file)
50 Ebb.log.puts ">> Writing PID to #{file}"
51 open(file,"w+") { |f| f.write(Process.pid) }
52 File.chmod(0644, file)
58 @parser = OptionParser.new
62 :threaded_processing => true
66 def parse_options(argv)
67 @parser.banner = "Usage: #{self.class} [options] start | stop"
69 extra_options if respond_to?(:extra_options)
72 # opts.on("-s", "--socket SOCKET", "listen on socket") { |socket| options[:socket] = socket }
73 @parser.on("-p", "--port PORT", "(default: #{@options[:port]})") { |p| @options[:port]=p }
74 @parser.on("-d", "--daemonize", "Daemonize") { @options[:daemonize] = true }
75 @parser.on("-l", "--log-file FILE", "File to redirect output") { |f| @options[:log_file]=f }
76 @parser.on("-P", "--pid-file FILE", "File to store PID") { |f| @options[:pid_file]=f }
77 # @parser.on("-t", "--timeout SECONDS", "(default: #{@options[:timeout]})") { |s| @options[:timeout]=s }
80 @parser.on_tail("-h", "--help", "Show this message") do
84 @parser.on_tail('-v', '--version', "Show version") do
85 Ebb.log.puts "Ebb #{Ebb::VERSION}"
97 Ebb.log.print("Ebb is loading the application...")
100 Ebb.log.puts("loaded")
102 if @options[:daemonize]
103 pwd = Dir.pwd # Current directory is changed during daemonization, so store it
106 trap('HUP', 'IGNORE') # Don't die upon logout
109 if @options[:log_file]
110 [STDOUT, STDERR].each { |f| f.reopen @options[:log_file], 'a' }
113 if @options[:pid_file]
114 Runner.write_pid_file(@options[:pid_file])
116 Ebb.log.puts ">> Exiting!"
117 Runner.remove_pid_file(@options[:pid_file])
121 Ebb::start_server(@app, @options)
123 Ebb::Runner.kill @options[:pid_file], @options[:timeout]
125 Ebb.log.puts "Command required"
129 abort "Invalid command : #{argv[0]}"