Debugging: Konsolenausgabe und Upstart-Skripte


16

Wie kann man die Ausgabe eines Upstart-Skripts an ein Terminal senden, um Tracebacks im Python-Code zu finden? Ich brauche eine Ewigkeit, um Dinge zu tun, die keine Rückverfolgung erfordern und früher nur eine Sekunde gedauert haben. Ich muss mehrere Aufrufe zum Schreiben von Dateien ausführen, um Fehler aufzuspüren. Was zuvor mit einem Traceback in Sekundenschnelle gefunden wurde, ist, dass es sich um einige Minuten Minuten handelt. Das ist miserabel. Das geht jetzt schon ein paar Wochen so und ich habe es satt. Würden sich bitte einige dazu äußern? Ich habe das Gefühl, dass ich wieder Assembly ohne Debugger verwende.

Antworten:


27

Wenn Sie Upstart 1.4 oder höher verwenden, geben Sie dies console login Ihren Upstart-Job ein, und alle Ausgaben an stdout / stderr werden auf enden /var/log/upstart/<job>.log. Anschließend können Sie tail -f /var/log/upstart/<job>.log &die Ausgabe im Terminal anzeigen lassen.


Es ist ein bisschen spät auf der Party, aber diese Antwort hat mich gerettet :) Sieht auch so aus, als würde das bei mir ohne spezielle Einstellung in der upstart conf-Datei funktionieren. Für meinen Teil sollte dies die akzeptierte Antwort sein.
Rslite

Wusste nicht, dass verwaltete Upstart-Dienstprotokolle angemeldet sind /var/log/upstart. Wirklich nützlich, danke.
Francisco

2

Es gibt einen ganzen Abschnitt über Debugging-Techniken im Upstart-Kochbuch . Das Einfachste, was Sie tun können, ist --debug, Ihre Kernel-Argumente zu erweitern, was die Ausführlichkeit von upstart erhöht und alles in syslog ablegt. Ja, das Debuggen ist komplex und spiegelt die Netzkomplexität wider, die zum Erstellen eines parallelisierten Init-Systems erforderlich ist. Ich bin sicher, es gibt Raum für Verbesserungen.


2
Das Kochbuch erklärt einem Neuling die Debug-Umgebung nicht richtig. Ich habe schon ähnliche Erklärungen gesehen. Es gibt entweder fehlende oder Guru-Annahmen. Es ist sehr frustrierend für Leute, die der Community etwas hinzufügen wollen und gerade erst anfangen. Ich bin noch nie auf eine Programmierumgebung gestoßen, die nicht die Codezeile enthält, in der der Fehler auftritt, außer in der Assembly, in der Sie das Rad neu erfinden, damit das vergeben werden kann.
Bambuntu

Nun, was würden Sie dann vorschlagen? Es ist ein offenes Dokument. Wenn Sie eine Debugging-Technik haben, die weit über den dort angebotenen Möglichkeiten liegt, fügen Sie sie bitte hinzu. Die Probleme des OP sind eher darauf zurückzuführen, dass er nicht versteht, wie grundlegende Unix-Paradigmen innerhalb der zusätzlichen Laufzeit seiner Wahl im Vergleich zum Kontext, in dem es bereitgestellt wird, verwaltet werden. Nur weil Sie Python oder [hier eine ausgefallene Laufzeitsprache einfügen] verwenden, heißt das nicht, dass Sie dies tun Holen Sie sich die grundlegende Laufzeit, UNIX zu ignorieren.
ppetraki

2

Wenn ich einen Python-Daemon schreibe, fange ich alle Ausnahmen ab und werfe sie dann in die Protokolldatei. Ich benutze es nicht nur zum Debuggen, sondern auch in der Produktion. Ich habe ein kleines Skript, das ich jeden Morgen ausführe und das nach Störungen in den Protokollen sucht.

Es hilft natürlich auch dabei, den Daemon am Laufen zu halten.

Einige Beispielcodes (ich entferne die nicht interessanten Teile):

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)

Wobei actua () der eigentliche Daemon ist (er schreibt auch, um zu protokollieren). Beachten Sie, dass ich auch eine DEBUG-Variable in einer Einstellungsdatei habe. Wenn dies der Fall ist, wird der Dämon nicht gegabelt, sodass er auf der Konsole ausgeführt wird.

Daemons

Daemons sind das Unix-Äquivalent zu Windows-Diensten. Dies sind Prozesse, die unabhängig von anderen Prozessen im Hintergrund ausgeführt werden. Das bedeutet, dass ihr Vater normalerweise init ist und dass sie sich von jedem tty lösen. Da sie unabhängig sind, gibt es keinen vordefinierten Ort für die Ausgabe.

Es gibt viele Python-Bibliotheken und Snippets, um einen Daemon zu erstellen. Im obigen Beispiel verwende ich meine eigene Funktion, die einige Ideen aus den Versionen von Steinar Knutsens und Jeff Kunces kombiniert. Es ist so einfach wie möglich, beachte, dass ich zweimal gabele .

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()

Gut, ok. Da Sie sich bereits bei Syslog anmelden, filtern Sie einfach Ihre Daemon-Nachrichten heraus und speichern Sie sie in der Konsole. Ich verstehe nicht, warum dies spezifisch für Emporkömmlinge ist. SysV init hätte das gleiche Problem.
ppetraki

Sie haben recht, es ist nicht spezifisch für einen Neustart, um ehrlich zu sein, die meisten meiner Server laufen mit 8.04, kein Neustart. Aber es gilt auch für Emporkömmlinge. OP fragte, wie man Python-Skripte mit upstart debuggt, nicht für eine Methode, die nur mit upstart funktioniert. Ich logge mich nicht in Syslog, sondern in einer bestimmten Datei ein. Der Trick besteht darin, alle Ausnahmen abzufangen und den Stack-Trace in diese Datei zu schreiben.
Javier Rivera

Nun, das ist nur das Verwalten von stdout basierend auf dem Kontext, oder? Ich kenne viele Unix-Daemons, die eine äquivalente Ausführlichkeit der Protokollierung aufweisen, unabhängig davon, ob sie mit einem tty verknüpft sind oder als Daemon fungieren. Wenn dies Ruby wäre, würde ich die Basisklassenmethode, die Ausnahmen für die Ausgabe verwenden, überschreiben oder dekorieren. Ich bin sicher, dass etwas Ähnliches in Python gemacht werden kann. Vielleicht ist es besser, diese Frage beim eigentlichen Stapelaustausch zu stellen. Dies ist eher ein grundlegendes Problem bei der Codierung / Gestaltung von Unix-Daemons, und wie Sie bereits sagten, hat es nichts spezielles mit Init-Skripten zu tun.
ppetraki

Ich werde immer noch mit dem Jargon vertraut. Ich gehe davon aus, dass Sie mit "Daemon" ein bestimmtes Skript meinen, das im Hintergrund ausgeführt wird. In Ihrem Code habe ich einfach mein Skript anstelle von actua () eingefügt, um die Rückrufe für diesen Skriptaufruf zu erhalten. Gibt es überhaupt eine Möglichkeit, es an eine Konsole anstatt an eine Datei zu leiten?
Bambuntu

1
Daemons im eigenständigen Sinn werden normalerweise von dem Tag getrennt, an dem sie gestartet wurden, haben ihre ursprünglichen Datei-Handles auf stdin, stdout und stdin geschlossen und sind ein Kind von init. Wenn Sie also Ausnahmen an einem bestimmten Ort drucken möchten, finden Sie heraus, wie sie ausgegeben werden, und leiten Sie sie von dort aus weiter. linfo.org/daemon.html . Auch dies hat nichts mit Emporkömmling oder gar Init zu tun. Stellen Sie sicher, dass Ihr Programm im True-Daemon-Modus ordnungsgemäß funktioniert, und verschieben Sie es anschließend nach oben.
ppetraki
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.