web-dev-qa-db-fra.com

Débogage: Scripts de sortie de la console et Upstart

Comment envoyer la sortie d'un script upstart à un terminal pour trouver des traces dans le code python? Cela me prend pour toujours de faire des choses sans traces qui ne prenaient qu'une seconde. Je dois passer plusieurs appels en écriture de fichier pour localiser les erreurs. Ce qui a pris une seconde à trouver avant avec un retraçage revient à plusieurs minutes minutes. C'est misérable. Cela dure depuis quelques semaines maintenant et j'en ai marre. est-ce que certains pourraient en parler, s'il vous plaît? J'ai l'impression que j'utilise à nouveau Assembly sans un débogueur.

16
bambuntu

Si vous utilisez Upstart 1.4 ou une version plus récente, insérez console log dans votre travail Upstart et toute la sortie sur stdout/stderr se terminera par /var/log/upstart/<job>.log. Ensuite, vous pouvez faire tail -f /var/log/upstart/<job>.log & pour que la sortie apparaisse dans le terminal.

27
Tuminoid

Il existe toute une section sur les techniques de débogage dans le pstart Cookbook . La chose la plus simple que vous puissiez faire est d’ajouter --debug à vos arguments du noyau, ce qui augmentera la verbosité de upstart et videra tout dans syslog. Oui, le débogage est complexe, il reflète la complexité du réseau nécessaire pour créer un système init parallélisé. Je suis sûr qu'il y a place à l'amélioration.

2
ppetraki

Lorsque j'écris un démon python, j'attrape toutes les exceptions et jette ensuite le fichier journal. J'utilise non seulement pour le débogage, mais aussi en production. J'ai un petit script que je lance tous les matins et qui cherche quelque chose de bouleversant dans les journaux.

Cela aide également à garder le démon en marche, bien sûr.

Quelques exemples de code (je supprime les parties non intéressantes):

import logging

if __== "__main__":
    logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s %(levelname)s %(message)s',
                    filename=LOG_FILE,
                    filemode='w')
    logging.info("Sincrod inicializado")
    if not DEBUG:
        daemonize()
    while True:
        try:
            actua()
        except:
            logging.error(sys.exc_info())
        if (datetime.datetime.now().hour > NOITE_EMPEZA\
         and datetime.datetime.now().hour < NOITE_REMATA):
            time.sleep(INTERVALO_NOITE)
        else:
            time.sleep(INTERVALO_DIA)

Où actua () est le véritable démon (il écrit également dans le journal). Notez que j'ai aussi une variable DEBUG dans un fichier de paramètres. Quand c'est True, je ne branche pas le démon, il est donc exécuté sur la console.

Daemons

Les démons sont l'équivalent Unix des services Windows. Ce sont des processus qui s'exécutent en arrière-plan, indépendamment des autres processus. Cela signifie que leur père est généralement init et qu'ils sont détachés de tout tty. Comme ils sont indépendants, il n'y a pas d'endroit prédéfini pour mettre leur sortie.

Il existe de nombreuses bibliothèques et extraits python pour créer un démon. Dans l'exemple ci-dessus, j'utilise ma propre fonction, qui combine certaines idées des versions de Steinar Knutsens et de Jeff Kunces. C'est aussi simple que possible, notez que je bifurque deux fois .

def daemonize():
    """Forks this process creating a daemon and killing the original one"""
    if (not os.fork()):
        # get our own session and fixup std[in,out,err]
        os.setsid()
        sys.stdin.close()
        sys.stdout = NullDevice()
        sys.stderr = NullDevice()
        if (not os.fork()):
            # hang around till adopted by init
            ppid = os.getppid()
            while (ppid != 1):
                time.sleep(0.5)
                ppid = os.getppid()
        else:
            # time for child to die
            os._exit(0)
    else:
        # wait for child to die and then bail
        os.wait()
        sys.exit()
2
Javier Rivera