Débogage: sortie de la console et scripts de démarrage

16

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

bambuntu
la source

Réponses:

27

Si vous utilisez Upstart 1.4 ou une version plus récente, placez-la console logdans votre tâche Upstart et toutes les sorties vers stdout / stderr finiront /var/log/upstart/<job>.log. Ensuite, vous pouvez faire tail -f /var/log/upstart/<job>.log &en sorte que la sortie apparaisse dans le terminal.

Tuminoïde
la source
Un peu tard pour la fête, mais cette réponse m'a sauvé :) On dirait aussi que cela fonctionne pour moi sans aucun paramètre spécial dans le fichier de configuration upstart. Pour ma part, cela devrait être la réponse acceptée.
rslite
Je ne savais pas que les journaux des services gérés arrivants étaient entrés /var/log/upstart. Vraiment utile, merci.
Francisco
2

Il y a une section entière sur les techniques de débogage dans le livre de recettes Upstart . La chose la plus simple que vous puissiez faire est d'ajouter --debugà vos arguments de noyau, ce qui augmentera la verbosité de upstart et tout vider dans syslog. Oui, le débogage est complexe, c'est le reflet de la complexité nette requise pour créer un système d'initialisation parallélisé. Je suis sûr qu'il y a place à amélioration.

ppetraki
la source
2
le livre de cuisine n'explique pas correctement un environnement de débogage à un nouveau venu. J'ai déjà vu des explications similaires. Il y a soit des failles, soit des hypothèses de gourou. C'est très frustrant pour les gens qui veulent ajouter à la communauté et qui commencent tout juste. Je n'ai jamais rencontré un environnement de programmation qui n'a pas fourni la ligne de code où l'erreur se produit, sauf dans l'assemblage, où vous réinventez la roue, ce qui peut être pardonné.
bambuntu
Eh bien, que suggéreriez-vous alors? C'est un document ouvert. Si vous avez une technique de débogage qui va au-delà de ce qui est présenté ici, veuillez l'ajouter. Les problèmes de l'OP sont plus le résultat de ne pas comprendre comment gérer les paradigmes Unix de base à l'intérieur de son exécution supplémentaire de choix par rapport au contexte dans lequel il est déployé. Ce n'est pas parce que vous utilisez python ou [insérer un langage d'exécution sophistiqué ici] que vous arriver à ignorer le runtime fondamental, UNIX.
ppetraki
2

Lorsque j'écris un démon python, j'attrape toutes les exceptions et les jette ensuite dans le fichier journal. Je l'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 à maintenir le démon en marche, bien sûr.

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

import logging

if __name__ == "__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 aussi pour se connecter). Notez que j'ai également une variable DEBUG dans un fichier de paramètres, quand c'est vrai, je ne bifurque pas le démon donc il s'exécute sur la console.

Démons

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 de place prédéfinie pour mettre leur sortie.

Il existe de nombreuses bibliothèques et extraits de code 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 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()
Javier Rivera
la source
Bon, d'accord. puisque vous vous connectez déjà à syslog, il vous suffit de filtrer vos messages démon et de les vider sur la console. Je ne vois pas pourquoi cela est spécifique à parvenu? SysV init aurait le même problème.
ppetraki
Vous avez raison, ce n'est pas spécifique à upstart, à vrai dire la plupart de mes serveurs exécutent la 8.04, pas d'upstart. Mais c'est également valable pour les nouveaux arrivants. OP demandait comment déboguer des scripts python avec upstart, pas pour une méthode qui ne fonctionne qu'avec upstart. Je ne me connecte pas à syslog mais à un fichier spécifique, et l'astuce consiste à intercepter toutes les exceptions et à vider la trace de la pile dans ce fichier.
Javier Rivera
eh bien, c'est juste gérer stdout en fonction du contexte, non? Je connais beaucoup de démons Unix qui ont une verbosité de journalisation équivalente, qu'il soit attaché à un tty ou fonctionnant comme un démon. S'il s'agissait de Ruby, je remplacerais ou décorerais la méthode de classe de base que les exceptions utilisent pour produire. Je suis sûr que quelque chose de similaire peut être fait en Python. Vous pourriez être mieux servi de poser cette question sur l'échange de pile proprement dit. Il s'agit davantage d'un problème de base de codage / conception du démon Unix, et comme vous l'avez dit, cela n'a rien de spécifique à voir avec les scripts d'initialisation.
ppetraki
Je me familiarise toujours avec le jargon. Je suppose que par démon, vous voulez dire un script spécifique qui s'exécute en arrière-plan. Dans votre code, je viens de mettre mon script à la place de actua () pour obtenir les rappels pour cet appel de script? Est-il possible de le canaliser vers une console au lieu d'un fichier?
bambuntu
1
les démons au sens autonome sont généralement détachés du tty sur lequel ils ont été démarrés, ont fermé leurs descripteurs de fichiers d'origine à stdin, stdout et stdin et sont un enfant d'init. Donc, si vous souhaitez imprimer des exceptions dans un endroit spécifique, découvrez comment elles sont sorties et dirigez-les à partir de là. linfo.org/daemon.html . Encore une fois, cela n'a rien à voir avec upstart, ni même init d'ailleurs. Faites fonctionner votre programme correctement en mode démon réel, puis déplacez-le par le haut.
ppetraki