#!/usr/bin/env ruby if File.exists?("magent.init.rb") require './magent.init' elsif File.exist?("config/environments") && File.exist?("app/models") # rails require Dir.getwd + '/config/environment' end $:.unshift File.dirname(__FILE__)+"/../lib/" require 'magent' require 'optparse' require 'fileutils' def usage(option_parser, error = nil) $stderr.puts error if error $stderr.puts option_parser exit 1 end options = {:piddir => "/tmp", :type => :async, :queue => :default} optparser = OptionParser.new do |opts| opts.banner = "Usage: #{$0} [options] -Q \n\nExample: magent -d -P /tmp -Q default restart\n\nOptions:" opts.on("-a PATH", "--agent=PATH", "Path to agent") do |o| options[:agent] = o options[:type] = :actor end opts.on("-Q QUEUE", "--queue=QUEUE", "queue to use. default=default") do |o| options[:queue] = o end opts.on("-t ID", "--identifier=ID", "Identifier") do |o| options[:identifier] = o end opts.on("-d", "--daemonize", "Run agent as a daemon") do |o| options[:daemonize] = true end opts.on("-l", "--log-path=PATH", "Log path") do |o| options[:log_path] = o end opts.on("-P", "--piddir=PATH", "PID dir to use (if daemonized)", "Default: #{options[:piddir]}") do |o| options[:piddir] = o end opts.on_tail("-h", "--help", "Show this help message.") do puts opts exit end end args = [] begin args = optparser.parse! rescue => e $stderr.puts e $stderr.puts optparser exit 0 end if args.empty? usage(optparser, "not enough arguments") end if options[:agent] load options[:agent] end class Controller attr_reader :options def initialize(opts) @options = opts @queue = @options[:queue] @options[:log_path] ||= Dir.getwd @identity = @options[:identifier] || Magent::Utils.underscore(@options[:queue].to_s) @identity << "-#{Socket.gethostname.split('.')[0]}" $stderr.puts ">> Starting magent in #{@options[:type]} model" end def start if @options[:daemonize] && @options[:piddir] run_as_daemon else Magent::Processor.new(self.channel).run! end end def stop begin pid = File.read(pid_file).to_i Process.kill("TERM", pid) Process.kill(0, pid) Process.wait rescue Errno::ECHILD, Errno::ESRCH => e $stdout.puts "Process #{pid} has stopped" rescue Errno::ENOENT => e $stdout.puts "Warning: #{e}" ensure File.unlink(pid_file) if File.exist?(pid_file) end end def restart begin stop rescue => e $stderr.puts "Warning: #{e}" end start end def channel @channel ||= (@options[:type] == :async) ? Magent::AsyncChannel.new(@queue) : Magent::ActorChannel.new(@queue) end private def run_as_daemon daemonize FileUtils.mkpath(@options[:piddir]) if @options[:piddir] File.open(pid_file, "w") do |f| f.write(Process.pid) end end Magent::Processor.new(self.channel).run! end def pid_file @pid_file ||= File.join(@options[:piddir], "magent.#{@identity}.pid") end def daemonize exit if fork Process.setsid exit if fork STDIN.reopen "/dev/null" STDOUT.reopen "#{@options[:log_path]}/magent.#{@identity}.out", "a" STDERR.reopen "#{@options[:log_path]}/magent.#{@identity}.err", "a" STDERR.sync = true STDOUT.sync = true end end Controller.new(options).send(args.shift)