require 'optparse' require 'glue/configuration' require 'nitro/compiler' #require 'facet/kernel/autoreload' require 'glue/autoreload' module Nitro # The Runner is a helper class that encapsulates a web # application and is responsible for launching the # application in different modes. # # The runner provides default parsing of command line # and environment parameters. # # You can implement your own, custom version of the Runner # to run your custom web applications. #-- # WARNING: this class will be deprecated! # FIXME: Trim this class, most functionality goes to bin/nitro. #++ class Runner # :start, :stop, :restart attr_accessor :action # The server used to run this web application. # :webrick, :nitro, :lhttp, :apache, :mod_apache # # At the moment only :webrick and :lhttp are available. attr_accessor :server # Run as daemon. attr_accessor :daemon # Spidering mode. Acceptable values are :crawl, :render # and false. attr_accessor :spider # Parse the command line arguments and the environment # parameters to setup the application. def setup_options @action ||= :start @daemon = false @spider = false # Setup from command line arguments. parser = OptionParser.new do |opts| opts.banner = 'Usage: run.rb [options]' opts.separator '' opts.separator 'Specific options:' opts.on('-s', '--start', 'Start application.') do @action = :start end opts.on('-S', '--stop', 'Stop application.') do @action = :stop end opts.on('-r', '--restart', 'Restart application.') do @action = :restart end opts.on('-d', '--daemon', 'Run application as a daemon.') do @daemon = true end opts.on('-D', '--debug', 'Run application in debug mode.') do Configuration.mode = :debug end opts.on('-T', '--stage', 'Run application in stage mode.') do Configuration.mode = :stage end opts.on('-L', '--live', 'Run application in live mode.') do Configuration.mode = :live end opts.on('--address IP', 'Force the server to run on this address.') do |a| @server_address = a end opts.on('--port PORT', 'Force the server to run on this port.') do |p| @server_port = p.to_i end opts.on('--port_offset PORT', 'The port offset in the cluster.') do |o| @server_port_offset = o.to_i end opts.on('-w', '--webrick', 'Use a webrick server [default].') do Nitro.adapter = :webrick end opts.on('-m', '--mongrel', 'Use the Mongrel Ruby server.') do Nitro.adapter = :mongrel # FIXME: handle logging. end opts.on('-l', '--lhttpd', 'Use a lighttpd server (FastCGI).') do Nitro.adapter = :lhttpd Logger.set(Logger.new('log/app.log')) end opts.on('-l', '--lhttpd-scgi', 'Use the SCGI adapter (Lighttpd).') do Nitro.adapter = :lhttpd_scgi Logger.set(Logger.new('log/app.log')) end opts.on('-a', '--apache', 'Use an apache server.') do Nitro.adapter = :apache Logger.set(Logger.new('log/app.log')) end opts.on('--apache-cgi', 'Use the CGI adapter (Apache)') do Nitro.adapter = :cgi Logger.set(Logger.new('log/app.log')) end opts.on('--scgi', 'Use the generic SCGI adapter') do Nitro.adapter = :scgi end opts.on('--crawl', 'Crawl the application.') do Nitro.adapter = :webrick @spider = :crawl end opts.on('--render', 'Crawl the application and render all pages as static html files.') do Nitro.adapter = :webrick @spider = :render end opts.on_tail('-h', '--help', 'Show this message.') do puts opts exit end # Hack fix for bin/nitro. opts.on_tail('-v', '--verbose', 'Verbose mode') do # nop, hack fix. end opts.on('--destroy') do # nop, hack fix. end opts.on('-C', '--console', 'Start a console attached to an instance of the application.') do # nop, hack fix. end opts.on('--app', 'The application name') do |adapter| # nop, hack fix. end opts.on('--mode', 'Set the execution mode') do |adapter| # nop, hack fix. end opts.on('--adapter', 'Set the adapter to use') do |adapter| # nop, hack fix. end opts.on('--record', 'Record the application server session to the given file.') do |filename| # nop, hack fix. end opts.on('--playback', 'Playback a previously recorded session from the given file.') do |filename| # nop, hack fix. end opts.on('--cluster', 'Setup a cluster.') do |ic| # nop, hack fix. end end parser.parse!(ARGV) return self end # Setup the declared execution mode, # using the passed configuration parameters. def setup_mode case Configuration.mode when :debug setup_debug when :stage setup_stage when :live setup_live end # Special setup for distributed sessions. =begin if defined?(Session) and defined?(DRbObject) if Session.store.is_a?(DRbObject) system('ruby ' + File.join(Nitro::LibPath, 'session', 'drbserver.rb') + ' --address #{Session.drb_address} --port #{Session.drb_port} --daemon') end end =end end # Setup in debug mode. def setup_debug $DBG = true Compiler.reload = true autoreload(3) Caching.caching_enabled = false # load_external_configuration(:debug) end def setup_stage $DBG = false Compiler.reload = true autoreload(3) Logger.set(Logger.new('log/app.log')) # load_external_configuration(:stage) end def setup_live $DBG = false # Enable the reloading even on live apps by default. # But have a longer thread sleep time. # If you really need sligthly faster dispatching enable # reloading (Compiler.reload = false) Compiler.reload = true autoreload(2 * 60) Logger.set(Logger.new('log/app.log')) # load_external_configuration(:live) # load_external_configuration(:production) end alias_method :setup_production, :setup_live # ... def invoke(server) case ENV['NITRO_INVOKE'] when 'fcgi_proc' require 'nitro/adapter/fastcgi' FastCGI.start(server) when 'scgi_proc' require 'nitro/adapter/scgi' Scgi.start(server) when 'cgi_proc' require 'nitro/adapter/cgi' CgiAdapter.start(server) when 'irb' require 'nitro/adapter/console' require 'nitro/caching/proxy' $server = server $app = ConsoleAdapter.new(server) $cache = Caching::Proxy else invoke_server(server) end end # ... def invoke_server(server) spider_thread = nil # FIXME refactor ! server.address = @server_address if @server_address server.port = @server_port if @server_port server.port += @server_port_offset if @server_port_offset case @action when :start case @spider when :render spider_thread = Thread.new do sleep(6) `wget -k -m -p #{server.address}:#{server.port} -directory-prefix=rendered` end when :crawl spider_thread = Thread.new do sleep(6) `wget -m --spider #{server.host}:#{server.port}` end end @server = Nitro.adapter Logger.info "" Logger.info "Setup for #{Configuration.mode} mode." case @server when :webrick require 'nitro/adapter/webrick' Logger.info "Starting Webrick on #{server.address}:#{server.port}" Logger.info "Press Ctrl-C to shutdown; Run with --help for options." Logger.info "" Webrick.start(server) when :mongrel require 'nitro/adapter/mongrel' Logger.info "Starting Mongrel on #{server.address}:#{server.port}" Logger.info "Press Ctrl-C to shutdown; Run with --help for options." Logger.info "" Mongrel.start(server) when :lhttpd require 'nitro/adapter/fastcgi' puts "==> Launching lighttpd (FastCGI)." `lighttpd -f conf/lhttpd_fcgi.conf` when :apache require 'nitro/adapter/fastcgi' puts "==> Launching apache (FastCGI)." `apachectl -d #{Dir.pwd} -f conf/apache.conf -k start` when :cgi require 'nitro/adapter/cgi' puts "==> Using standard CGI. Please look into using Fast/Scgi" end when :stop case @server when :webrick when :lhttpd when :apache `apachectl -d #{Dir.pwd} -f conf/apache.conf -k stop` end end end # :section: Utilities # Run this proccess as a daemon (UNIX only). def daemonize require 'daemons/daemonize' pwd = Dir.pwd Daemonize.daemonize(File.join(pwd, 'log/app.log')) # Restore the original pwd (daemonize sets the # pwd to '/'). Dir.chdir(pwd) # Save a process sentinel file. FileUtils.touch ".a#{Process.pid}.pid" # Set the logger to a file (daemonize closes the # std streams). Logger.set(Logger.new('log/app.log')) end # Attempt to load external configuration in Ruby or # YAML format. The files: # # * conf/mode.rb # * conf/mode.yaml # # are considered. def load_external_configuration(mode = :debug) # require "conf/#{mode}.rb" ruby_conf = "conf/#{mode}.rb" load ruby_conf if File.exist?(ruby_conf) # Try to configure from a yaml file. yml_conf = "conf/#{mode}.yml" Configuration.load yml_conf if File.exist?(yml_conf) end end Run = Runner end