Linux Complex Bash One-Liner Beispiele
Bash-Einzeiler können die Arbeitsbelastung reduzieren, etwas schnell automatisieren und die Macht der ultimativen Systemkontrolle in Ihre Hände legen. Im Laufe der Zeit werden Sie wahrscheinlich lernen, komplexere Einzeiler zu schreiben, und einige der Dinge, die Sie als erfahrener Profi schreiben, werden von einem Anfänger fast nicht analysiert werden können. Das heißt, die Bash-Befehls- und Entwicklungssprache ist sehr strukturiert – und relativ leicht zu verstehen – sobald Sie die Ein- und Ausgänge kennen. Es ist wirklich, als würden Sie eine Fremdsprache beherrschen.
In diesem Tutorial lernen Sie:
- So schreiben Sie fortgeschrittenere Bash-Einzeiler-Befehle und -Skripte
- Verstehen, wie Sie verschiedene Befehle in einzeiligen Skripten kombinieren
- Verstehen, wie sich Exit-Codes von einem Befehl auf andere Befehle auswirken können, wenn
&&und|| - Verstehen, wie Eingaben aus einem Befehl geändert und dann vom nächsten Befehl verwendet werden können.
- Verwendung und reale Beispiele für fortgeschrittenere Bash-Einzeiler
Linux Complex Bash One-Liner Beispiele
Verwendete Softwareanforderungen und Konventionen
Beispiel 1: Prozesssteuerung
Beginnen wir mit einem Beispiel, wie bestimmte Prozesse in Bash auf leicht verständliche Weise beendet werden können:
sleep 3600 &
[1] 1792341
ps -ef | grep 'sleep'
roel 1792441 1701839 0 12:59 pts/13 00:00:00 sleep 3600
roel 1792452 1701839 0 12:59 pts/13 00:00:00 grep --color=auto sleep
Zuerst richten wir einen Schlafbefehl für 3600 Sekunden (eine Stunde) ein und finden diesen Prozess anschließend in der Prozessliste. Großartig, aber wir haben den eigentlichen grep-Befehl als zusätzliche Zeile in der Ausgabe der Prozessauflistung. Lassen Sie uns das filtern und als nächstes die Prozess-ID anstelle der vollständigen Prozessinformationsausgabe extrahieren:
ps -ef | grep 'sleep' | grep -v grep
roel 1792441 1701839 0 12:59 pts/13 00:00:00 sleep 3600
ps -ef | grep 'sleep' | grep -v grep | awk '{print $2}'
1792441
Im ersten Befehl haben wir das aktive grep herausgefiltert. Im zweiten Befehl sind wir noch einen Schritt weiter gegangen, indem wir die zweite Spalte $2 (innerhalb von awk) mit dem Befehl awk ausgegeben haben. Wir können jetzt noch einen Schritt weiter gehen und diesen Prozess tatsächlich beenden. Nehmen wir an, wir machen das mit Signal 9, das für jeden Linux-Prozess (SIGKILL) sehr zerstörerisch ist:
ps -ef | grep 'sleep' | grep -v grep | awk '{print $2}' | xargs kill -9
[1]+ Killed sleep 3600
Und wir können sehen, dass unser Prozess korrekt beendet wurde. Obwohl dies ein einfacheres Beispiel war, umfasste es 6 verschiedene Befehle: ps, grep, grep again, awk, xargs und kill. Sie können sehen, wie Bash-Einzeiler auf viele verschiedene Arten und auf vielen verschiedenen Ebenen der Komplexität und Datenverarbeitungsfähigkeit schnell Komplexität aufbauen können.
Und um mehr über xargs zu erfahren, lesen Sie bitte unsere Artikel xargs für Anfänger mit Beispielen und Multithreaded xargs mit Beispielen.
Beispiel 2: Spaß an Erfolg und Misserfolg!
echo '0' > a && echo '1' > b && echo '2' > c && ls doesnotexist || ls a && ls b && ls c && ls d && ls e
ls: cannot access 'doesnotexist': No such file or directory
a
b
c
ls: cannot access 'd': No such file or directory
Was für eine komplexe Linie! Doch wenn man einmal weiß, wie man es liest, oder vielleicht tut man es bereits, wird es sehr leicht zu lesen. Lassen Sie uns diese Behauptung als gültig demonstrieren, indem wir den Befehl in kleinere, mundgerechte Stücke aufteilen, die leichter zu verstehen und zu befolgen sind:
echo '0' > a && echo '1' > b && echo '2' > c
Alles, was dieser Satz von Befehlen tut, ist identisch mit dem folgenden, mit einer kleinen Einschränkung:
echo '0' > a
echo '1' > b
echo '2' > c
Was ist also der Unterschied (und die kleine Einschränkung)?
Dass in dieser letzten Befehlsreihe jeder Befehl ausgeführt wird, unabhängig davon, was das Ergebnis des vorherigen Befehls war. Die vorherige Sequenz (mit &&) fährt nur dann mit dem zweiten Echo fort, wenn das Ergebnis des ersten Befehls 0 war (d. h. Erfolg – in Bash wird der Erfolg eines Befehls durch 0 und der Fehler mit 1 oder höher als Exit-Code angezeigt).
Somit könnte die Befehlssequenz mit && auch wie folgt geschrieben werden;
echo '0' > a
if [ ${?} -eq 0 ]; then echo '1' > b; fi
if [ ${?} -eq 0 ]; then echo '2' > c; fi
Die Variable $ {?} (oder $? in Kurzsyntax) enthält immer das Ergebnis des letzten Befehls, d.h. den Exit-Code (0, 1 oder höher), der durch den letzten Befehl generiert wurde.
Wie wir sehen können, ist die einzeilige Erstellung von echo '0' > a && echo '1' > b & & echo '2' > c jetzt sicherlich einfacher für die Augen und das Verständnis und reduziert definitiv die Komplexität des entsprechenden und passenden Codes, der direkt oben angezeigt wird.
Nehmen wir als nächstes nur noch einen weiteren Befehl:
echo '0' > a && echo '1' > b && echo '2' > c && ls doesnotexist
ls: cannot access 'doesnotexist': No such file or directory
Das liest sich jetzt viel einfacher, oder?
Wir haben gerade einen weiteren Befehl hinzugefügt, nämlich ls doesnotexist, vorausgesetzt, dass der Befehl davor (und in diesem Fall die ganze Zeile, da alle Befehle durch && in einem kettenartigen Setup verbunden sind, bei dem ein fehlerhafter Befehl die Kette unterbricht und die Ausführung der Kette vollständig stoppt) erfolgreich war. Da alle Befehle erfolgreich sind, wird ls ausgeführt, und es wird ein Fehler als Ergebnis desselben erzeugt, da die Datei, nun ja, wirklich nicht existiert 🙂
Was würde also passieren, wenn wir am Ende noch ein && anschließen würden? Würde die Befehlskette enden, wie wir gesagt haben? Passen wir den Befehl ein wenig an:
echo '0' > a && echo '1' > b && echo '2' > c && ls doesnotexist && echo 'surely not'
ls: cannot access 'doesnotexist': No such file or directory
Und sicherlich hat es nicht funktioniert. Lassen Sie uns dann unseren nächsten Befehl in unserer Kette aus dem ursprünglichen Beispiel einführen:
echo '0' > a && echo '1' > b && echo '2' > c && ls doesnotexist || ls a
ls: cannot access 'doesnotexist': No such file or directory
a
Können Sie sehen, was passiert? Hier haben wir ein neues Syntaxsymbol, nämlich ||, das sich von && dadurch unterscheidet, dass es nur ausgeführt wird, wenn es im vorherigen Befehl ein Ergebnis ungleich Null gab. Beachten Sie, dass sowohl || als auch && nur für den letzten Befehl gelten und nicht für die Befehlskette, auch wenn man sie sich insgesamt als Kette vorstellen könnte.
Man kann sich also && als das englische Äquivalent und and vorstellen, bis zu einem gewissen Grad das Übliche und Vorhandene in Programmiersprachen, aber mit der Wendung, dass wir hier vor dem && auf eine Bedingung prüfen und ausführen, was dahinter steht, vorausgesetzt, die Beendigungsbedingung ist 0.
Eine weitere Wendung besteht darin, dass die meisten Programmiersprachen bei Verwendung der &&-Syntax als binäre 1 auf Richtigkeit prüfen. Betrachten Sie zum Beispiel den Pseudo-Code; wenn test1_flag & & test2_flag dann... was in der Regel insgesamt als wahr ausgewertet wird (und somit die then-Befehle ausführt), wenn die binären Flags test1_flag und test2_flag 1 oder wahr sind, während in Bash die Wahrhaftigkeit durch einen 0 (und nicht 1) Exit-Status des letzten Befehls angezeigt wird!
Sie können sich || als das Äquivalent der englischen Sprache vorstellen oder (oder wie in oder wenn dies fehlschlägt, dann tun...). In dieser Situation besteht ein stärkerer Zusammenhang mit gängigen Programmiersprachen: Wenn eine gängige Programmiersprache z.B. prüft, ob test1_flag || test2_flag dann ..., dann würde ein binäres positives test1_flag (d.h. Wert 1) oder test2_flag ergeben, dass die Gesamtbedingung wahr ist (und somit die then-Klausel ausgeführt wird). Das Gleiche sehen wir bei Bash; Wenn der Exit-Code des Befehls ungleich Null ist (d. h. in einigen Fällen 1 oder ein höherer Wert), wird der Befehl hinter der || Klausel ausgeführt.
Gehen wir nun zurück zum ursprünglichen Befehl und analysieren ihn vollständig:
echo '0' > a && echo '1' > b && echo '2' > c && ls doesnotexist || ls a && ls b && ls c && ls d && ls e
ls: cannot access 'doesnotexist': No such file or directory
a
b
c
ls: cannot access 'd': No such file or directory
Können Sie sehen, was passiert? Da der Befehl ls doesnotexist intern fehlschlägt und eine Ausgabe ungleich Null liefert (verwenden Sie ls doesnotexist; echo $? in Bash zur Überprüfung; die Ausgabe ist 2), wird die Klausel or (||) ausgelöst und als nächstes führen wir ls aus. Stell es dir wie eine Kette vor, die in eine andere Richtung fließt, aber es ist immer noch eine Kette.
Wenn der Befehl ls a erfolgreich ist und die Klausel and (&&) folgt, wird der nächste Befehl ausgeführt usw. Beachten Sie, dass die Ausführung an ls d geht und die Ausgabe dafür (ls: nicht auf 'd' zugreifen kann: Keine solche Datei oder kein solches Verzeichnis) angezeigt wird, aber der Befehl ls e wird nicht ausgeführt! Dies ist zu erwarten, da && verwendet wurde und der Befehl ls d fehlgeschlagen ist. Daher wird ls e nie ausgeführt.
Schlussfolgerung
Je geübter Sie im Schreiben von Bash-Einzeilern werden, desto schneller, besser, weniger fehleranfällig und flüssiger werden Ihre Bash-Einzeiler-Skripte und desto weniger Zeit verbringen Sie mit dem Schreiben. Die Entwickler der Bash-Sprache haben die gesamte Kontrolle in Ihre Hände gelegt. Was werden Sie heute mit dieser Kontrolle machen?
Hinterlassen Sie uns unten eine Nachricht mit Ihren coolsten Einzeiler-Kreationen!
