Ich habe ein Verzeichnis mit Absturzprotokollen und möchte eine bedingte Anweisung in einem Bash-Skript verwenden, das auf einem find-Befehl basiert.
Die Protokolldateien werden in folgendem Format gespeichert:
/var/log/crashes/app-2012-08-28.log
/var/log/crashes/otherapp-2012-08-28.log
Ich möchte, dass die if-Anweisung nur dann true zurückgibt, wenn ein Absturzprotokoll für eine bestimmte App vorhanden ist, das in den letzten 5 Minuten geändert wurde. Der find
Befehl, den ich verwenden würde, ist:
find /var/log/crashes -name app-\*\.log -mmin -5
Ich bin mir nicht sicher, wie ich das if
richtig in eine Aussage einbauen soll . Ich denke, das könnte funktionieren:
if [ test `find /var/log/crashes -name app-\*\.log -mmin -5` ] then
service myapp restart
fi
Es gibt einige Bereiche, in denen ich unklar bin:
- Ich habe mir die if-Flags angesehen , bin mir aber nicht sicher, welche ich verwenden soll.
- Benötige ich die
test
Direktive oder sollte ich nur direkt mit den Ergebnissen des Befehls find verfahren oderfind... | wc -l
stattdessen eine Zeilenzählung durchführen? - Nicht zu 100% notwendig, um diese Frage zu beantworten, sondern
test
zum Testen von Rückgabecodes, die von Befehlen zurückgegeben werden? Und sie sind irgendwie unsichtbar - außerhalb vonstdout
/stderr
? Ich habe dieman
Seite gelesen , bin mir aber immer noch ziemlich unklar, wann ich sie verwendentest
und wie ich sie debuggen soll.
find ... -exec
. Siehe auch die Beispielbefehle unter Warum wird die Ausgabe von find nicht ordnungsgemäß wiederholt?... -exec command ';' -quit
, aber ich glaube nicht, dass es für Letzteres eine andere Lösung gibt, als das Ergebnis zu analysieren. Außerdem tritt in beiden Fällen das Hauptproblem beim Analysieren des Ergebnisses vonfind
(dh der Unfähigkeit, Trennzeichen von Zeichen in Dateinamen zu unterscheiden) nicht auf, da in diesen Fällen keine Trennzeichen gefunden werden müssen.Antworten:
[
undtest
sind Synonyme (außer[
erfordert]
), daher möchten Sie Folgendes nicht verwenden[ test
:test
Gibt einen Exit-Status von Null zurück, wenn die Bedingung erfüllt ist, andernfalls ungleich Null. Dies kann tatsächlich durch ein beliebiges Programm ersetzt werden, um den Beendigungsstatus zu überprüfen. Dabei gibt 0 Erfolg und Nicht-Null Fehler an:Alle obigen Beispiele testen jedoch nur den Exit-Status des Programms und ignorieren die Programmausgabe.
Für
find
müssen Sie testen, ob eine Ausgabe generiert wurde.-n
testet auf eine nicht leere Zeichenkette:Eine vollständige Liste der Testargumente können Sie
help test
über diebash
Befehlszeile aufrufen .Wenn Sie verwenden
bash
(und nichtsh
), können Sie verwenden[[ condition ]]
, was sich vorhersehbarer verhält, wenn sich in Ihrem Zustand Leerzeichen oder andere Sonderfälle befinden. Ansonsten ist es im Allgemeinen dasselbe wie beim Verwenden[ condition ]
. Ich habe[[ condition ]]
in diesem Beispiel verwendet, wie ich es mache, wann immer es möglich ist.Ich habe auch
`command`
zu$(command)
, was auch im Allgemeinen ähnlich verhält, aber ist schöner mit verschachtelten Befehlen.quelle
echo
kann scheitern: versuchenecho 'oops' > /dev/full
.find
Wird erfolgreich beendet, wenn keine Fehler aufgetreten sind. Sie können sich also nicht auf den Beendigungsstatus verlassen, um festzustellen, ob eine Datei gefunden wurde. Wie Sie bereits sagten, können Sie jedoch die Anzahl der gefundenen Dateien zählen und diese Zahl testen.Es wäre ungefähr so:
test
(aka[
) überprüft die Fehlercodes der Befehle nicht, es hat eine spezielle Syntax, um Tests durchzuführen, und wird dann mit einem Fehlercode von 0 beendet, wenn der Test erfolgreich war, oder 1, wenn dies nicht der Fall ist. Es istif
derjenige, der den Fehlercode des Befehls überprüft, den Sie an ihn übergeben, und den Hauptteil darauf basierend ausführt.Siehe
man test
(oderhelp test
, wenn Sie verwendenbash
) undhelp if
(dito).In diesem Fall
wc -l
wird eine Zahl ausgegeben. Wir verwendentest
die Option-gt
, um zu testen, ob diese Anzahl größer als ist0
. Wenn dies der Fall ist, wirdtest
(oder[
) mit dem Beendigungscode zurückgegeben0
.if
interpretiert diesen Exit-Code als Erfolg und führt den Code in seinem Körper aus.quelle
Das wäre
oder
Die Befehle
test
und[ … ]
sind genau das Gleiche. Der einzige Unterschied ist ihr Name und die Tatsache,[
dass ein Abschluss]
als letztes Argument erforderlich ist . Verwenden Sie wie immer doppelte Anführungszeichen um die Befehlsersetzung, andernfalls wird die Ausgabe desfind
Befehls in Wörter aufgeteilt, und hier wird ein Syntaxfehler angezeigt, wenn mehr als eine übereinstimmende Datei vorhanden ist (und wenn keine Argumente vorhanden sind,[ -n ]
ist dies wahr) , während Sie wollen,[ -n "" ]
was falsch ist).In ksh, bash und zsh, aber nicht in ash, können Sie auch verwenden,
[[ … ]]
die unterschiedliche Parsing-Regeln haben:[
ist ein gewöhnlicher Befehl, wohingegen[[ … ]]
es sich um ein anderes Parsing-Konstrukt handelt. Sie brauchen keine doppelten Anführungszeichen[[ … ]]
(obwohl sie nicht schaden). Du brauchst noch das;
nach dem Befehl.Dies kann möglicherweise ineffizient sein: Wenn viele Dateien vorhanden sind, durchsucht
/var/log/crashes
find sie alle. Sie sollten find stoppen lassen, sobald es eine Übereinstimmung findet, oder kurz danach. Verwenden Sie bei GNU find (nicht eingebettetes Linux, Cygwin) das-quit
primäre.Bei anderen Systemen muss die Verbindung hergestellt
find
werdenhead
, um mindestens kurz nach dem ersten Spiel zu beenden (der Fund stirbt an einer kaputten Leitung).(Sie können verwenden,
head -c 1
wenn Ihrhead
Befehl dies unterstützt.)Alternativ können Sie auch zsh verwenden.
quelle
Das sollte funktionieren
quelle
ist hier eine passende Lösung.
-exec service myapp restart ';'
ruftfind
den Befehl auf, den Sie direkt ausführen möchten, anstatt dass die Shell etwas interpretieren muss.-quit
führtfind
dazu, dass der Befehl nach der Verarbeitung des Befehls beendet wird, wodurch verhindert wird, dass der Befehl erneut ausgeführt wird, wenn mehrere Dateien vorhanden sind, die den Kriterien entsprechen.quelle