#!/usr/bin/env ruby # thin start: Starts the Rails app in the current directory. # Run thin -h to get more usage. require File.dirname(__FILE__) + '/../lib/thin' require 'optparse' COMMANDS = %w(start stop restart) # Default options values options = { :chdir => Dir.pwd, :environment => 'development', :address => '0.0.0.0', :port => 3000, :timeout => 60, :log => 'log/thin.log', :pid => 'tmp/pids/thin.pid', :servers => 1 # no cluster } # NOTE: If you add an option here make sure the key in the +options+ hash is the # same as the name of the command line option. # +option+ keys are use to build the command line to launch a cluster, # see lib/thin/cluster.rb. opts = OptionParser.new do |opts| opts.banner = "Usage: thin [options] #{COMMANDS.join('|')}" opts.separator "" opts.separator "Server options:" opts.on("-a", "--address HOST", "bind to HOST address (default: 0.0.0.0)") { |host| options[:address] = host } opts.on("-p", "--port PORT", "use PORT (default: 3000)") { |port| options[:port] = port.to_i } opts.on("-e", "--environment ENV", "Rails environment (default: development)") { |env| options[:environment] = env } opts.on("-c", "--chdir PATH", "Change to dir before starting") { |dir| options[:chdir] = File.expand_path(dir) } opts.on("-s", "--servers NUM", "Number of servers to start", "set a value >1 to start a cluster") { |num| options[:servers] = num.to_i } opts.on("-d", "--daemonize", "Run daemonized in the background") { options[:daemonize] = true } opts.on("-l", "--log FILE", "File to redirect output", "(default: #{options[:log]})") { |file| options[:log] = file } opts.on("-P", "--pid FILE", "File to store PID", "(default: #{options[:pid]})") { |file| options[:pid] = file } opts.on("-t", "--timeout SEC", "Request or command timeout in sec", "(default: #{options[:timeout]})") { |sec| options[:timeout] = sec.to_i } opts.on("-u", "--user NAME", "User to run daemon as (use with -g)") { |user| options[:user] = user } opts.on("-g", "--group NAME", "Group to run daemon as (use with -u)") { |group| options[:group] = group } opts.on( "--prefix PATH", "Mount the app under PATH (start with /)") { |path| options[:prefix] = path } opts.separator "" opts.separator "Common options:" opts.on_tail("-D", "--debug", "Set debbuging on") { $DEBUG = true } opts.on_tail("-h", "--help", "Show this message") { puts opts; exit } opts.on_tail('-v', '--version', "Show version") { puts Thin::SERVER; exit } opts.parse! ARGV end # == Commands definitions def cluster?(options) options[:servers] && options[:servers] > 1 end def start(options) if cluster?(options) Thin::Cluster.new(options).start else server = Thin::Server.new(options[:address], options[:port]) server.pid_file = options[:pid] server.log_file = options[:log] server.timeout = options[:timeout] if options[:daemonize] server.daemonize server.change_privilege options[:user], options[:group] if options[:user] && options[:group] end server.app = Rack::Adapter::Rails.new(options.merge(:root => options[:chdir])) # If a prefix is required, wrap in Rack URL mapper server.app = Rack::URLMap.new(options[:prefix] => server.app) if options[:prefix] server.start! end end def stop(options) if cluster?(options) Thin::Cluster.new(options).stop else Thin::Server.kill options[:pid], options[:timeout] end end def restart(options) if cluster?(options) Thin::Cluster.new(options).restart else # Restart only make sense when running as a daemon options.update :daemonize => true stop(options) start(options) end end # == Runs the command Dir.chdir(options[:chdir]) command = ARGV[0] if COMMANDS.include?(command) send(command, options) elsif command.nil? puts "Command required" puts opts exit 1 else abort "Invalid command : #{command}" end