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
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 diesefoo
bar
Beispiele 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.Antworten:
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 beinhaltetinit
(undsystemd
), einschließlichrc.local
. Wenn dieser Daemon nicht mit Root-Rechten ausgeführtsudo
wird, funktioniert er nur, wenn er/etc/sudoers
so konfiguriert ist (und ohne Kennwort). Raspbian-Benutzer können dadurch verwirrt sein, da derpi
Benutzer standardmäßig alles tun darf (und wenn Sie hineinschauen, werden/etc/sudoers
Sie sehen, wie dies erreicht wird).Als Nächstes können Sie die Ausgabe eines beliebigen
bash
Skripts oder eines beliebigen Befehlssatzes in einem Bash-Skript erfassen , indem Sie sie in einer Subshell wie folgt ausführen: 1Das
()
zeigt eine Unterschale an . Alle Ausgaben von irgendetwas in diesem werden in eine/var/log/myTestLog.txt
Datei umgeleitet . Ein paar Anmerkungen:&>
ist ein Bashismus . Wenn das Skript also über einen Shebang in der ersten Zeile ausgeführt wird, sollte dies#!/bin/bash
nicht nur der Fall sein/bin/sh
. "Bashisms" funktionieren nur in derbash
Shell.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/log
erfordert 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/tmp
jedoch 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 überschreibenmyTestLog.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: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-v
bedeutet "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 $?
. VersuchenSie erhalten 0 und 2. Wenn Sie dann in der Manpage
ls
unter "Status beenden" nachsehen , sehen Sie das eher unspezifische, kryptische: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:
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/foo
es nicht funktioniert, nicht gefunden werden kann usw.,sudo bar
wird 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:
Oben (oder irgendwo anders, und es gilt für alles, was danach folgt).
quelle
Ein wichtiger Aspekt, den Menschen beim Ausführen von Skripten als Dämonen häufig vergessen, ist die Shell-Umgebung und
$PATH
insbesondere die Variable. In Ihrem Beispiel basiert die zweite Zeile auf$PATH
: dem vollständigen Namen vonsudo
is/usr/bin/sudo
, und Ihre Benutzer-Shell weiß das nur, weil sie angewiesen wurde,/usr/bin
bei der Suche nach ausführbaren Dateien zu suchen . Gleiches gilt fürbar
.Da dies
sudo
beim Ausführen von Skripten als Dämonen nicht erforderlich ist, sollte Ihre zweite Zeile folgendermaßen aussehen:quelle