From eff60cfe6dcdfc45fc4e3d9fc158becaaf390efc Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Thu, 20 Jul 2006 17:17:15 +0000 Subject: [PATCH] Add --background option to daemonize the bot --- bin/rbot | 7 +++- lib/rbot/ircbot.rb | 86 +++++++++++++++++++++++++++++++++++++--------- 2 files changed, 76 insertions(+), 17 deletions(-) diff --git a/bin/rbot b/bin/rbot index 14b57d7c..812c44f5 100755 --- a/bin/rbot +++ b/bin/rbot @@ -36,12 +36,16 @@ opts = GetoptLong.new( ["--debug", "-d", GetoptLong::NO_ARGUMENT], ["--help", "-h", GetoptLong::NO_ARGUMENT], ["--trace", "-t", GetoptLong::REQUIRED_ARGUMENT], - ["--version", "-v", GetoptLong::NO_ARGUMENT] + ["--version", "-v", GetoptLong::NO_ARGUMENT], + ["--background", "-b", GetoptLong::NO_ARGUMENT] ) $debug = false +$daemonize = false + opts.each {|opt, arg| $debug = true if(opt == "--debug") + $daemonize = true if(opt == "--background") $opts[opt.sub(/^-+/, "")] = arg } @@ -79,6 +83,7 @@ if ($opts["help"]) puts " -h, --help this message" puts " -v, --version version information" puts " -d, --debug enable debug messages" + puts " -b, --background background (daemonize) the bot" puts "config directory defaults to ~/.rbot" exit 0 end diff --git a/lib/rbot/ircbot.rb b/lib/rbot/ircbot.rb index 8e6fabac..88a85483 100644 --- a/lib/rbot/ircbot.rb +++ b/lib/rbot/ircbot.rb @@ -98,19 +98,6 @@ class IrcBot BotConfig.register BotConfigIntegerValue.new('server.reconnect_wait', :default => 5, :validate => Proc.new{|v| v >= 0}, :desc => "Seconds to wait before attempting to reconnect, on disconnect") - BotConfig.register BotConfigStringValue.new('irc.nick', :default => "rbot", - :desc => "IRC nickname the bot should attempt to use", :wizard => true, - :on_change => Proc.new{|bot, v| bot.sendq "NICK #{v}" }) - BotConfig.register BotConfigStringValue.new('irc.user', :default => "rbot", - :requires_restart => true, - :desc => "local user the bot should appear to be", :wizard => true) - BotConfig.register BotConfigArrayValue.new('irc.join_channels', - :default => [], :wizard => true, - :desc => "What channels the bot should always join at startup. List multiple channels using commas to separate. If a channel requires a password, use a space after the channel name. e.g: '#chan1, #chan2, #secretchan secritpass, #chan3'") - BotConfig.register BotConfigIntegerValue.new('core.save_every', - :default => 60, :validate => Proc.new{|v| v >= 0}, - # TODO change timer via on_change proc - :desc => "How often the bot should persist all configuration to disk (in case of a server crash, for example") BotConfig.register BotConfigFloatValue.new('server.sendq_delay', :default => 2.0, :validate => Proc.new{|v| v >= 0}, :desc => "(flood prevention) the delay between sending messages to the server (in seconds)", @@ -128,6 +115,35 @@ class IrcBot :on_change => Proc.new {|bot, v| bot.start_server_pings}, :desc => "reconnect if server doesn't respond to PING within this many seconds (set to 0 to disable)") + BotConfig.register BotConfigStringValue.new('irc.nick', :default => "rbot", + :desc => "IRC nickname the bot should attempt to use", :wizard => true, + :on_change => Proc.new{|bot, v| bot.sendq "NICK #{v}" }) + BotConfig.register BotConfigStringValue.new('irc.user', :default => "rbot", + :requires_restart => true, + :desc => "local user the bot should appear to be", :wizard => true) + BotConfig.register BotConfigArrayValue.new('irc.join_channels', + :default => [], :wizard => true, + :desc => "What channels the bot should always join at startup. List multiple channels using commas to separate. If a channel requires a password, use a space after the channel name. e.g: '#chan1, #chan2, #secretchan secritpass, #chan3'") + + BotConfig.register BotConfigIntegerValue.new('core.save_every', + :default => 60, :validate => Proc.new{|v| v >= 0}, + # TODO change timer via on_change proc + :desc => "How often the bot should persist all configuration to disk (in case of a server crash, for example)") + # BotConfig.register BotConfigBooleanValue.new('core.debug', + # :default => false, :requires_restart => true, + # :on_change => Proc.new { |v| + # debug ((v ? "Enabling" : "Disabling") + " debug output.") + # $debug = v + # debug (($debug ? "Enabled" : "Disabled") + " debug output.") + # }, + # :desc => "Should the bot produce debug output?") + BotConfig.register BotConfigBooleanValue.new('core.run_as_daemon', + :default => false, :requires_restart => true, + :desc => "Should the bot run as a daemon?") + BotConfig.register BotConfigStringValue.new('core.logfile', + :default => false, :requires_restart => true, + :desc => "Name of the logfile to which console messages will be redirected when the bot is run as a daemon") + @argv = params[:argv] unless FileTest.directory? Config::datadir @@ -157,7 +173,43 @@ class IrcBot @last_ping = nil @startup_time = Time.new @config = BotConfig.new(self) -# TODO background self after botconfig has a chance to run wizard + # background self after botconfig has a chance to run wizard + @logfile = @config['core.logfile'] + if @logfile.class!=String || @logfile.empty? + @logfile = File.basename(botclass)+".log" + end + if @config['core.run_as_daemon'] + $daemonize = true + end + # See http://blog.humlab.umu.se/samuel/archives/000107.html + # for the backgrounding code + if $daemonize + begin + exit if fork + Process.setsid + exit if fork + rescue NotImplementedError + puts "Could not background, fork not supported" + $daemonize = false + rescue => e + puts "Could not background. #{e.inspect}" + $daemonize = false + end + end + + if $daemonize + Dir.chdir botclass + # File.umask 0000 # Ensure sensible umask. Adjust as needed. + begin + STDIN.reopen "/dev/null" + rescue Errno::ENOENT + # On Windows, there's not such thing as /dev/null + STDIN.reopen "NUL" + end + STDOUT.reopen @logfile, "a" + STDERR.reopen STDOUT + end + @timer = Timer::Timer.new(1.0) # only need per-second granularity @registry = BotRegistry.new self @timer.add(@config['core.save_every']) { save } if @config['core.save_every'] @@ -342,11 +394,13 @@ class IrcBot trap("SIGINT") { got_sig("SIGINT") } trap("SIGTERM") { got_sig("SIGTERM") } trap("SIGHUP") { got_sig("SIGHUP") } + rescue ArgumentError => e + debug "failed to trap signals (#{e.inspect}): running on Windows?" rescue => e - debug "failed to trap signals: #{e.inspect}\nProbably running on windows?" + debug "failed to trap signals: #{e.inspect}" end begin - @socket.connect + @socket.connect unless $interrupted > 0 rescue => e raise e.class, "failed to connect to IRC server at #{@config['server.name']} #{@config['server.port']}: " + e end -- 2.39.2