Protokollausgabe des Hintergrund- oder Boot-Skripts

10

Ich habe ein kurzes Skript, das von einem Systemdämon für bestimmte Ereignisse ausgeführt wird. Ich weiß, dass das Ereignis eintritt und das Skript ausgeführt wird, aber es tut nicht das, was ich beabsichtige. Seltsamerweise funktioniert es, wenn ich es manuell ausführe, daher bin ich sehr verwirrt.

Wie kann ich herausfinden, was los ist? Das Skript besteht im Wesentlichen aus einer Reihe solcher Befehle:

/bin/foo on 3
sudo bar a
Goldlöckchen
quelle
Ich verstehe, dass dies ein Tutorial zum Debuggen von Systemskripten sein soll, aber auch ein bisschen U&L. Ich habe den Titel falsch verstanden und würde vorschlagen, dass "Protokollieren der Ausgabe eines Systemskripts zum Debuggen" den Zweck klarer macht. Auch mein Gehirn friert ein, wenn ich diese foo barBeispiele lese . Ich bevorzuge etwas, das realer aussieht. Ich zögere es, Beiträge zu bearbeiten. Ich überlasse dies Ihnen, wenn Sie der Meinung sind, dass sie verbessert werden können.
Milliways
1
@ Milliways Du hast Recht, "System-Skript" war sowieso eine Art Fehlbezeichnung, also habe ich den Titel geändert. Ich bin nicht einverstanden mit der Foobar-Sache - die Leute müssen lernen, gängige Umgangssprache / Umgangssprache zu erkennen, so wie sie es in jeder Kultur tun könnten. Auch ist es immer noch ein gutes Kichern, wenn Sie die beiden zusammenfügen.
Goldlöckchen

Antworten:

8

Wenn das Skript von einem Systemdämon ausgeführt wird und dieser Dämon mit Root-Rechten ausgeführt wird, müssen Sie es zunächst nicht verwenden sudo. Dies beinhaltet init(und systemd), einschließlich rc.local. Wenn dieser Daemon nicht mit Root-Rechten ausgeführt sudowird, funktioniert er nur, wenn er /etc/sudoersso konfiguriert ist (und ohne Kennwort). Raspbian-Benutzer können dadurch verwirrt sein, da der piBenutzer standardmäßig alles tun darf (und wenn Sie hineinschauen, werden /etc/sudoersSie sehen, wie dies erreicht wird).

Als Nächstes können Sie die Ausgabe eines beliebigen bashSkripts oder eines beliebigen Befehlssatzes in einem Bash-Skript erfassen , indem Sie sie in einer Subshell wie folgt ausführen: 1

(
    /bin/foo on 3
    sudo bar a
) &> /var/log/myTestLog.txt

Das ()zeigt eine Unterschale an . Alle Ausgaben von irgendetwas in diesem werden in eine /var/log/myTestLog.txtDatei umgeleitet . Ein paar Anmerkungen:

  • &>ist ein Bashismus . Wenn das Skript also über einen Shebang in der ersten Zeile ausgeführt wird, sollte dies #!/bin/bashnicht nur der Fall sein /bin/sh. "Bashisms" funktionieren nur in der bashShell.

    Dies schließt ein /etc/rc.local, was standardmäßig verwendet wird /bin/sh(dh ja, Sie können dies sicher in ändern /bin/bash).

  • /var/logerfordert Root-Rechte zum Schreiben. Wenn der Prozess nicht über ein solches verfügt, verwenden oder erstellen Sie ein Verzeichnis, von dem Sie wissen, dass es dies kann. Wenn Sie im Zweifelsfall dies testen können, ohne das System herunterfahren oder neu starten zu müssen, verwenden Sie /tmp, was weltweit beschreibbar ist (dh von jedermann). Bleibt /tmpjedoch nicht über Stiefel hinweg bestehen. Es ist auch eine kleine RAM-basierte Partition. Schreiben Sie also keine Datenmengen darauf. Es ist nicht Ihre SD-Karte [tatsächlich auf aktuellen Versionen von Raspbian, aber rechnen Sie in der Praxis nicht damit] .

  • &>wird alles in überschreiben myTestLog.txt. Wenn Sie stattdessen an ein vorhandenes Protokoll anhängen möchten, was für Debugging-Zwecke eine gute Idee sein könnte, verwenden Sie &>>. Sie können dann am Anfang dieser Unterschale einen Befehl wie folgt hinzufügen:

    echo Starting $(date)

    Um die Informationen von jedem Lauf zu trennen. Wenn Sie sich nicht sicher sind, was dies bewirkt, versuchen Sie es in der Befehlszeile.

Dieser letzte Punkt ist ein gutes Beispiel dafür, was Sie in Bezug auf Befehle tun können, die nichts ausgeben - aber die meisten tun dies, wenn Sie z. B. -v"ausführlich" einschließen . Vorsicht bei einigen Befehlen -vbedeutet "Versionsinformationen drucken". Schauen Sie in der Manpage nach dem Befehl, um sicherzugehen, ob und wie dies funktioniert (einige Befehle verwenden auch einen anderen Schalter als -v).

Konventionell geben Befehle nach Abschluss auch den Wert 0 zurück. Dies wird manchmal als "Exit-Status" bezeichnet und wird normalerweise nicht angezeigt, aber die Shell zeigt es Ihnen an echo $?. Versuchen

 ls /
 echo $?
 ls /nonexistantdir
 echo $?

Sie erhalten 0 und 2. Wenn Sie dann in der Manpage lsunter "Status beenden" nachsehen , sehen Sie das eher unspezifische, kryptische:

2      if serious trouble (e.g., cannot access command-line argument).

Was vielleicht besser ist oder nicht als nichts, aber los geht's.

Zumindest bedeutet dies, dass der Befehl aus irgendeinem Grund fehlgeschlagen ist. Mit dem Exit-Status können Sie auch Folgendes tun:

/bin/foo && sudo bar

Das bedeutet &&in diesem Fall "wenn der erste Befehl erfolgreich ist", vorausgesetzt, der erste Befehl verwendet die Konvention der Rückgabe von 0 (weshalb dies normalerweise der Fall ist). Wenn /bin/fooes nicht funktioniert, nicht gefunden werden kann usw., sudo barwird es niemals passieren.

Die Verwendung einer Kombination aus Protokollierungsnachrichten und bedingter Ausführung ( &&) sollte Sie dem Herausfinden des Problems viel näher bringen oder zumindest Informationen abrufen, die für andere bei der Lösung des Problems hilfreich sein könnten. Ohne das kann niemand mehr raten.


1. Sie können dieselbe Ausgabeausleitung für ein gesamtes Skript von innen ausführen, indem Sie Folgendes verwenden:

exec &> /var/log/myTestLog.txt

Oben (oder irgendwo anders, und es gilt für alles, was danach folgt).

Goldlöckchen
quelle
2

Ein wichtiger Aspekt, den Menschen beim Ausführen von Skripten als Dämonen häufig vergessen, ist die Shell-Umgebung und $PATHinsbesondere die Variable. In Ihrem Beispiel basiert die zweite Zeile auf $PATH: dem vollständigen Namen von sudois /usr/bin/sudo, und Ihre Benutzer-Shell weiß das nur, weil sie angewiesen wurde, /usr/binbei der Suche nach ausführbaren Dateien zu suchen . Gleiches gilt für bar.

Da dies sudobeim Ausführen von Skripten als Dämonen nicht erforderlich ist, sollte Ihre zweite Zeile folgendermaßen aussehen:

/path/to/bar a
Dmitry Grigoryev
quelle