Website-Suche

Nützliche Bash-Befehlszeilen-Tipps und -Tricks, Beispiele - Teil 1


Die Bash-Befehlszeile bietet nahezu unbegrenzte Leistung, wenn es darum geht, fast alles auszuführen, was Sie tun möchten. Ganz gleich, ob es sich um die Verarbeitung einer Reihe von Dateien, die Bearbeitung einer Reihe von Dokumenten, den Umgang mit Big Data, die Verwaltung eines Systems oder die Automatisierung einer Routine handelt, Bash kann alles. Diese Serie, von der wir heute den ersten Teil vorstellen, wird Sie mit Sicherheit mit den Werkzeugen und Methoden ausstatten, die Sie benötigen, um ein viel kompetenterer Bash-Benutzer zu werden. Selbst bereits fortgeschrittene Benutzer werden wahrscheinlich etwas Neues und Aufregendes mitnehmen. Genießen!

In diesem Tutorial lernen Sie:

  • Nützliche Tipps, Tricks und Methoden zur Bash-Befehlszeile
  • So interagieren Sie mit der Bash-Befehlszeile auf fortgeschrittene Weise
  • Wie du deine Bash-Fähigkeiten insgesamt schärfst und ein kompetenterer Bash-Benutzer wirst

Nützliche Beispiele für Bash-Befehlszeilentipps und -tricks – Teil 1

Verwendete Softwareanforderungen und Konventionen

Beispiel 1: Ermitteln, welche Prozesse auf eine bestimmte Datei zugreifen

Möchten Sie wissen, welche Prozesse auf eine bestimmte Datei zugreifen? Dies ist ganz einfach mit dem in Bash integrierten Befehl fuser möglich:

fuser -a /usr/bin/gnome-calculator
/usr/bin/gnome-calculator: 619672e
ps -ef | grep 619672 | grep -v grep
abc       619672    3136  0 13:13 ?        00:00:01 gnome-calculator

Wie wir sehen können, wird die Datei /usr/bin/gnome-calculator (eine Binärdatei) derzeit vom Prozess mit der ID 619672 verwendet. Beim Überprüfen dieser Prozess-ID mit ps finden wir bald heraus, dass der Benutzer abc den Rechner gestartet hat, und zwar um 13:13 Uhr.

Das e hinter der PID (Prozess-ID) soll anzeigen, dass es sich um eine ausführbare Datei handelt, die gerade ausgeführt wird. Es gibt verschiedene andere solcher Qualifikatoren, und Sie können man fuser verwenden, um sie zu sehen. Dieses Fixierwerkzeug kann sehr leistungsfähig sein, insbesondere wenn es in Kombination mit lsof (einer ls von geöffneten Dateien) verwendet wird:

Nehmen wir an, wir debuggen einen Remote-Computer für einen Benutzer, der mit einem Standard-Ubuntu-Desktop arbeitet. Der Benutzer hat den Rechner gestartet, und jetzt ist sein gesamter Bildschirm eingefroren. Wir möchten nun alle Prozesse, die in irgendeiner Weise mit dem gesperrten Bildschirm in Verbindung stehen, aus der Ferne beenden, ohne den Server neu zu starten, in der Reihenfolge, wie wichtig diese Prozesse sind.

lsof | grep calculator | grep "share" | head -n1
xdg-deskt    3111                                 abc  mem       REG              253,1          3009   12327296 /usr/share/locale-langpack/en_AU/LC_MESSAGES/gnome-calculator.mo
fuser -a /usr/share/locale-langpack/en_AU/LC_MESSAGES/gnome-calculator.mo
/usr/share/locale-langpack/en_AU/LC_MESSAGES/gnome-calculator.mo:  3111m  3136m 619672m 1577230m
ps -ef | grep -E "3111|3136|619672|1577230" | grep -v grep
abc         3111    2779  0 Aug03 ?        00:00:11 /usr/libexec/xdg-desktop-portal-gtk
abc         3136    2779  5 Aug03 ?        03:08:03 /usr/bin/gnome-shell
abc       619672    3136  0 13:13 ?        00:00:01 gnome-calculator
abc      1577230    2779  0 Aug04 ?        00:03:15 /usr/bin/nautilus --gapplication-service

Zuerst haben wir alle geöffneten Dateien, die vom Taschenrechner verwendet werden, mit lsof lokalisiert. Um die Ausgabe kurz zu halten, haben wir nur das oberste Ergebnis für eine einzelne freigegebene Datei aufgelistet. Als nächstes haben wir fuser verwendet, um herauszufinden, welche Prozesse diese Datei verwenden. Dadurch erhielten wir die PIDs. Schließlich suchten wir mit einem OR (|)-basierten Grep, um herauszufinden, welche die tatsächlichen Prozessnamen sind. Wir können sehen, dass der Rechner zwar um 13:13 Uhr gestartet wurde, die anderen Prozesse jedoch länger laufen.

Als nächstes könnten wir zum Beispiel einen kill -9 619672 ausgeben und prüfen, ob das Problem dadurch behoben wurde. Wenn nicht, könnten wir uns an Prozess 1577230 (den gemeinsam genutzten Nautilus-Dateimanager), Prozess 3136 (die übergreifende Shell) oder schließlich Prozess 3111 versuchen, obwohl dies wahrscheinlich einen erheblichen Teil der Desktop-Erfahrung des Benutzers zerstören würde und möglicherweise nicht einfach neu zu starten wäre.

Beispiel 2: Debuggen von Skripts

Sie haben also ein großartiges Skript mit viel komplexem Code geschrieben und es dann ausgeführt... und sehen einen Fehler in der Ausgabe, der auf den ersten Blick nicht viel Sinn ergibt. Selbst nach einer Weile des Debuggens bleiben Sie immer noch bei dem, was passiert ist, während das Skript ausgeführt wurde.

Bash -X zur Rettung! bash -x ermöglicht es einem, ein test.sh Skript auszuführen und genau zu sehen, was passiert:

#!/bin/bash
VAR1="Hello linuxconfig.org readers!"
VAR2="------------------------------"
echo ${VAR1}
echo ${VAR2}

Ausführung:

bash -x ./test.sh
+ VAR1='Hello linuxconfig.org readers!'
+ VAR2=------------------------------
+ echo Hello linuxconfig.org 'readers!'
Hello linuxconfig.org readers!
+ echo ------------------------------
------------------------------

Wie Sie sehen können, zeigte uns der Befehl bash -x Schritt für Schritt genau, was passiert ist. Sie können die Ausgabe dieses Befehls auch einfach an eine Datei senden, indem Sie 2>&1 | tee my_output.log an den Befehl anhängen:

bash -x ./test.sh 2>&1 | tee my_output.log
... same output ...
cat my_output.log
+ VAR1='Hello linuxconfig.org readers!'
+ VAR2=------------------------------
+ echo Hello linuxconfig.org 'readers!'
Hello linuxconfig.org readers!
+ echo ------------------------------
------------------------------

Die 2>&1 sendet den stderr (Standardfehlerausgabe: alle Fehler, die während der Ausführung auftreten) an stdout (Standardausgabe: hier lose definiert als die Ausgabe, die Sie normalerweise auf dem Terminal sehen) und erfasst alle Ausgaben von bash -x. Der Befehl tee erfasst alle Ausgaben von stdout und schreibt sie in die angegebene Datei. Wenn Sie jemals an eine Datei anhängen möchten (und nicht mit einer leeren Datei neu beginnen möchten), können Sie tee -a verwenden, wobei die Option -a sicherstellt, dass die Datei angehängt wird.

Beispiel 3: Ein häufiger Fallstrick: sh -x != bash -x

Das letzte Beispiel hat uns gezeigt, wie man bash -x verwendet, aber können wir auch sh -x verwenden? Die Tendenz für einige neuere Bash-Benutzer könnte darin bestehen, sh -x auszuführen, aber das ist ein Anfängerfehler; sh ist eine viel eingeschränktere Shell. Während bash auf sh basiert, hat es noch viele weitere Erweiterungen. Wenn Sie also sh -x zum Debuggen Ihrer Skripte verwenden, werden seltsame Fehler angezeigt. Möchten Sie ein Beispiel sehen?

#!/bin/bash

TEST="abc"
if [[ "${TEST}" == *"b"* ]]; then
  echo "yes, in there!"
fi

Ausführung:

./test.sh
yes, in there!
bash -x ./test.sh
+ TEST=abc
+ [[ abc == *\b* ]]
+ echo 'yes, in there!'
yes, in there!
sh -x ./test.sh
+ TEST=abc
+ [[ abc == *b* ]]
./test: 4: [[: not found

Hier sehen Sie ein kleines Testskript, test.sh das bei der Ausführung prüft, ob ein bestimmter Buchstabe (b) in einem bestimmten Eingabestring (wie durch die TEST-Variable definiert) vorkommt. Das Skript funktioniert hervorragend, und wenn wir bash -x verwenden, können wir sehen, dass die präsentierten Informationen, einschließlich der Ausgabe, korrekt aussehen.

Als nächstes geht die Verwendung von sh -x erheblich schief; Die sh-Shell kann [[ nicht interpretieren und schlägt sowohl in der sh -x-Ausgabe als auch in der Skriptausführung selbst fehl. Dies liegt daran, dass die in bash implementierte advanced if-Syntax in sh nicht vorhanden ist.

Beispiel 4: Uniq oder nicht einzigartig – das ist hier die Frage!

Wollten Sie schon immer eine Datei sortieren und nur die eindeutigen Einträge auflisten? Auf den ersten Blick scheint dies eine einfache Übung zu sein, wenn man den mitgelieferten Bash-Befehl uniq verwendet:

cat input.txt 
1
2
2
3
3
3
cat input.txt | uniq
1
2
3

Wenn wir jedoch unsere Eingabedatei ein wenig ändern, stoßen wir auf Eindeutigkeitsprobleme:

cat input.txt 
3
1
2
3
2
3
3
3
cat input.txt | uniq
3
1
2
3
2
3

Dies liegt daran, dass uniq standardmäßig benachbarte übereinstimmende Zeilen filtert, wobei übereinstimmende Zeilen mit dem ersten Vorkommen zusammengeführt werden, wie das uniq-Handbuch verdeutlicht. Oder mit anderen Worten, es werden nur Zeilen entfernt, die genau mit der vorherigen identisch sind.

Im Beispiel ist dies daran zu erkennen, dass die letzten drei 3 Zeilen zu einer einzigen "einzigartigen" 3 verdichtet werden. Dies ist wahrscheinlich nur in einer begrenzten Anzahl und in bestimmten Anwendungsfällen nutzbar.

Wir können uniq jedoch noch ein wenig weiter optimieren, um uns nur wirklich eindeutige Einträge zu geben, indem wir den Parameter -u verwenden:

cat input.txt  # Note that the '#' symbols were added after execution, to clarify something (read below)
3  #
1  #
2  #
3  #
2  #
3
3
3
cat input.txt | uniq -u 
3
1
2
3
2

Sieht immer noch ein wenig verwirrend aus, oder? Wenn Sie sich die Ein- und Ausgabe genau ansehen, können Sie sehen, dass nur Zeilen ausgegeben werden, die individuell eindeutig sind (wie im obigen Beispiel nach der Ausführung mit # gekennzeichnet).

Die letzten drei 3 Zeilen werden nicht ausgegeben, da sie als solche nicht eindeutig sind. Auch diese Methode der Einzigartigkeit wäre in realen Szenarien nur begrenzt anwendbar, obwohl es einige Fälle geben kann, in denen sie sich als nützlich erweisen kann.

Wir können eine geeignetere Lösung für die Einzigartigkeit erhalten, indem wir ein etwas anderes integriertes Bash-Tool verwenden. Sortieren:

cat input.txt 
1
2
2
3
3
3
cat input.txt | sort -u
1
2
3

WUSSTEN SIE SCHON?
Sie können den cat-Befehl in den obigen Beispielen weglassen und die Datei für uniq oder sort bereitstellen, um direkt daraus zu lesen? Beispiel:sort -u input.txt

Großartig! Dies kann in vielen Skripten verwendet werden, bei denen wir eine echte Liste einzigartiger Einträge haben möchten. Der zusätzliche Vorteil ist, dass die Liste gleichzeitig schön sortiert ist (obwohl wir es vielleicht vorgezogen haben, die Option -n zu verwenden, um auch in einer numerischen Reihenfolge nach dem numerischen Wert der Zeichenkette zu sortieren).

Schlussfolgerung

Es macht viel Freude, Bash als Ihre bevorzugte Linux-Befehlszeile zu verwenden. In diesem Tutorial haben wir eine Reihe nützlicher Tipps und Tricks zur Bash-Befehlszeile untersucht. Dies ist der Auftakt einer Reihe von Bash-Befehlszeilenbeispielen, die, wenn Sie mitmachen, Ihnen helfen werden, viel fortgeschrittener an und mit der Bash-Befehlszeile und -Shell zu werden!

Teilen Sie uns Ihre Gedanken mit und teilen Sie uns unten einige Ihrer eigenen coolen Bash-Befehlszeilentipps, Tricks und Fallstricke mit!

  • Nützliche Beispiele für Bash-Befehlszeilentipps und -tricks – Teil 1
  • Nützliche Beispiele für Bash-Befehlszeilentipps und -tricks – Teil 2
  • Nützliche Bash-Befehlszeilen-Tipps und -Tricks Beispiele – Teil 3
  • Nützliche Bash-Befehlszeilen-Tipps und Tricks, Beispiele – Teil 4
  • Nützliche Beispiele für Bash-Befehlszeilentipps und -tricks – Teil 5

Verwandte Artikel: