#!/usr/bin/env ruby $LOAD_PATH.unshift 'lib' require 'facets/more/command' require 'glue/configuration' # The default Nitro management script. Provides a number of # options for managing the lifecycle of Nitro applications. class NitroCommand < Console::Command # :section: Commands # The default action, starts the application. You can # alternatively use the start/run aliases. # # === Examples # # $ nitro # $ nitro start # $ nitro run def start # Start the state server. if File.exist?('state.rb') and Dir['.d*.pid'].empty? puts 'Starting state server' system 'ruby state.rb --daemon' end # Start the application servers. if f = application_file ARGV.delete('start') exec_application(f) if ic = @instance_count (ic.to_i-1).times do |i| exec_application(f, i + 1) end end else puts 'No application found!' # FIXME: better error mesage and/or show default app! end end alias default start alias run start # Stop all running application instances. def stop kill_processes('.a*.pid') end # Restart all application servers. def restart stop() start() end # Stop all running application instances and related # servers (for example drb servers) def kill kill_processes('.a*.pid') kill_processes('.d*.pid') end # Starts an IRB console attached to the web application. # # $ nitro console def console if RUBY_PLATFORM =~ /mswin32/ irb_name = 'irb.bat' else irb_name = 'irb' end ENV['NITRO_INVOKE'] = 'irb' if f = application_file ENV['CONFIGURATION_MODE'] = $DBG ? 'debug' : 'live' exec "#{irb_name} -r #{f} -r irb/completion --noinspect" end exit end # Setup a cluster. The input is the size of the cluster. # For example: # # $ nitro cluster 5 # # starts 5 instances that listen to consecutive port numbers. def __cluster(instance_count) @instance_count = instance_count idx = ARGV.index('--cluster') ARGV.delete_at(idx) ARGV.delete_at(idx) # cluster implies daemon mode. unless ARGV.include? '--daemon' ARGV << '--daemon' end end def __debug ARGV.delete('--debug') ENV['CONFIGURATION_MODE'] = 'debug' end alias __devel __debug def __stage ARGV.delete('--stage') ENV['CONFIGURATION_MODE'] = 'stage' end def __live ARGV.delete('--live') ENV['CONFIGURATION_MODE'] = 'live' end alias __production __live def __mongrel # gmosx: handled in runner. end def __daemon # gmosx: handled in runner. end def _v require 'nitro/version' puts "Nitro #{Nitro::Version}" exit end alias __version _v private # Typical application main file names. APPLICATION_FILES = %w{ run.rb start.rb conf.rb app.rb application.rb } # Find out the application main file. def application_file for f in APPLICATION_FILES if File.exist? f return f end end return false end # Start the application server. If a cluster is defined, # multiple instances of the application server are spawned. def exec_application(file, port_offset = nil) cmd = "ruby #{file} #{ARGV.join(' ')}" if port_offset cmd << " --port_offset #{port_offset}" end # Mark this invocation with the application name. # Useful to identify process when runing ps on Unix. Use # for example: # # ps aux | grep ruby cmd << " --app #{File.basename(Dir.pwd)}" system(cmd) end # Kill processes marked by .pid files. def kill_processes(pattern = '.*.pid') Dir[pattern].each do |f| pid = f.split('.')[1].slice(1..-1) begin Process.kill('TERM', pid.to_i) rescue # drink it! ensure File.unlink(f) end end end end NitroCommand.new.execute