From: Vincent Le Gallic Date: Wed, 18 Jul 2012 18:44:51 +0000 (+0200) Subject: Basile est maintenant daemonizable ! \o/ X-Git-Url: http://gitweb.pimeys.fr/?p=bots%2Fbasile.git;a=commitdiff_plain;h=0cb5d6ef6af1c35aa54bcd3082f3b6872bc67bcc Basile est maintenant daemonizable ! \o/ --- diff --git a/basile.py b/basile.py index 92dcbcc..374a594 100755 --- a/basile.py +++ b/basile.py @@ -5,8 +5,6 @@ # Un bot IRC qui, un jour, s'interfacera avec la Note Kfet 2015 -import irclib -import ircbot import threading import random import time @@ -14,6 +12,14 @@ import socket, ssl, json import pickle import re import os +import signal +import sys + +# Oui, j'ai recodé ma version d'irclib pour pouvoir rattrapper les SIGHUP +sys.path.insert(0, "/home/vincent/scripts/python-myirclib") +import irclib +import ircbot + from commands import getstatusoutput as ex # on récupère la config @@ -160,12 +166,18 @@ def is_night(): class UnicodeBotError(Exception): pass + +class CrashError(Exception): + """Pour pouvoir faire crasher Basile, parce que ça a l'air drôle""" + pass + def bot_unicode(chain): try: unicode(chain,"utf8") except UnicodeDecodeError as exc: raise UnicodeBotError + class Basile(ircbot.SingleServerIRCBot): def __init__(self,serveur,debug=False): temporary_pseudo=config.irc_pseudo+str(random.randrange(10000,100000)) @@ -307,11 +319,13 @@ class Basile(ircbot.SingleServerIRCBot): "kick": [None,None,"""KICK [] Kicke du channel (Il faut bien entendu que j'y sois op)."""], "die": [None,None,"""DIE - Me déconnecte du serveur IRC."""] + Me déconnecte du serveur IRC."""], + "crash": [None,None,"""CRASH + Me fait crasher"""] } helpmsg_default="Liste des commandes disponibles :\nHELP IDENTIFY DROP SOLDE" helpmsg_ops=" JOIN LEAVE QUIET NOQUIET LOST RECONNECT RELOAD" - helpmsg_overops=" SAY DO STAY NOSTAY OPS OVEROPS KICK DIE" + helpmsg_overops=" SAY DO STAY NOSTAY OPS OVEROPS KICK DIE CRASH" op,overop=auteur in self.ops, auteur in self.overops if len(message)==1: helpmsg=helpmsg_default @@ -432,10 +446,16 @@ class Basile(ircbot.SingleServerIRCBot): self.mourir() else: notunderstood=True + elif cmd=="crash": + if auteur in self.overops: + log(self.serveur,"priv",auteur," ".join(message)+"[successful]") + self.crash() + else: + notunderstood=True elif cmd=="reload": if auteur in self.ops: - reload(config) - serv.privmsg(auteur,"done") + self.reload(auteur) + log(self.serveur,"priv",auteur," ".join(message)+"[successful]") else: notunderstood=True elif cmd=="reconnect": @@ -581,7 +601,13 @@ class Basile(ircbot.SingleServerIRCBot): else: serv.privmsg(canal,("%s: %s"%(auteur,random.choice(config.quit_fail_messages))).encode("utf8")) log(self.serveur,canal,auteur,message+"[failed]") - + elif cmd == "reload": + if auteur in self.ops: + log(self.serveur, canal, auteur, message+"[successful]") + self.reload(canal) + elif cmd == "crash": + if auteur in self.overops: + self.crash() elif cmd in ["part","leave","dégage","va-t-en","tut'tiresailleurs,c'estmesgalets"]: if auteur in self.ops and (not (canal in self.stay_channels) or auteur in self.overops): @@ -828,13 +854,45 @@ class Basile(ircbot.SingleServerIRCBot): return self.serv.get_nickname() nick=property(_getnick) + def reload(self, auteur=None): + reload(config) + if auteur in [None, "SIGHUP"]: + towrite = "Config reloaded" + " (SIGHUP received)"*(auteur == "SIGHUP") + for to in config.report_bugs_to: + self.serv.privmsg(to, towrite) + log(self.serveur, towrite) + else: + self.serv.privmsg(auteur,"Config reloaded") + + def crash(self): + raise CrashError + + def start_as_daemon(self, outfile): + sys.stderr = Logger(outfile) + self.start() + + +class Logger(object): + """Pour écrire ailleurs que sur stdout""" + def __init__(self, filename="basile.full.log"): + self.filename = filename -if __name__=="__main__": - import sys + def write(self, message): + f = open(self.filename, "a") + f.write(message) + f.close() + +def main(): if len(sys.argv)==1: - print "Usage : basile.py [--debug]" + print "Usage : basile.py [--debug] [--no-output] [--daemon [--pidfile]] [--outfile]" + print " --outfile sans --no-output ni --daemon n'a aucun effet" exit(1) serveur=sys.argv[1] + if "--daemon" in sys.argv: + os.chdir("/home/basile/basile") + daemon = True + else: + daemon = False if "debug" in sys.argv or "--debug" in sys.argv: debug=True else: @@ -843,10 +901,40 @@ if __name__=="__main__": config.debug_stdout=False serveurs={"a♡":"acoeur.crans.org","acoeur":"acoeur.crans.org","acoeur.crans.org":"acoeur.crans.org", "irc":"irc.crans.org","crans":"irc.crans.org","irc.crans.org":"irc.crans.org"} + if "--no-output" in sys.argv or "--daemon" in sys.argv: + outfile = "/var/log/bots/basile.full.log" + for arg in sys.argv: + arg = arg.split("=") + if arg[0].strip('-') in ["out", "outfile", "logfile"]: + outfile = arg[1] + sys.stdout = Logger(outfile) try: serveur=serveurs[serveur] except KeyError: print "Server Unknown : %s"%(serveur) exit(404) basile=Basile(serveur,debug) - basile.start() + # Si on reçoit un SIGHUP, on reload la config + def sighup_handler(signum, frame): + basile.reload("SIGHUP") + signal.signal(signal.SIGHUP, sighup_handler) + if daemon: + child_pid = os.fork() + if child_pid == 0: + os.setsid() + basile.start_as_daemon(outfile) + else: + # on enregistre le pid de basile + pidfile = "/var/run/bots/basile.pid" + for arg in sys.argv: + arg = arg.split("=") + if arg[0].strip('-') in ["pidfile"]: + pidfile = arg[1] + f = open(pidfile, "w") + f.write("%s\n" % child_pid) + f.close() + else: + basile.start() + +if __name__ == "__main__": + main()