Spezielle Bash-Variablen mit Beispielen
Bash ist eine großartige Programmiersprache, mit der Sie komplexe Dinge wie Big Data-Manipulation ausführen oder einfach Server- oder Desktop-Management-Skripte erstellen können.
Die Einstiegsfähigkeiten, die für die Verwendung der Bash-Sprache erforderlich sind, sind recht gering, und Einzeiler-Skripte (ein häufig verwendeter Jargon, der mehrere Befehle anzeigt, die auf der Befehlszeile ausgeführt werden und ein Mini-Skript bilden) sowie reguläre Skripte können an Komplexität zunehmen (und wie gut sie geschrieben sind), wenn der Bash-Entwickler mehr lernt.
Das Erlernen der Verwendung spezieller Variablen in Bash ist ein Teil dieser Lernkurve. Während die speziellen Variablen ursprünglich kryptisch aussehen mögen: $$, $?, $*, \$0, $1 usw., werden die Dinge, sobald Sie sie verstehen und in Ihren eigenen Skripten verwenden, bald klarer und leichter zu merken sein.
In diesem Tutorial lernen Sie:
- So verwenden Sie spezielle Variablen in Bash
- Wie man Variablen richtig zitiert, auch spezielle Variablen
- Beispiele für die Verwendung spezieller Variablen über die Befehlszeile und Skripte
Spezielle Bash-Variablen mit Beispielen
Verwendete Softwareanforderungen und Konventionen
$$– zeigt die PID (Process Identifier) an
In diesem Beispiel verwenden wir die spezielle Variable
$$,um die PID (Process Identifier) für unser aktuelles Programm anzuzeigen. Dies funktioniert etwas anders, je nachdem, ob Sie diese Variable von der Befehlszeile aus verwenden:echo $$ 316204 ps -ef | grep -E "$$|PID" UID PID PPID C STIME TTY TIME CMD roel 316204 62582 0 11:53 pts/2 00:00:00 bash roel 316499 316204 0 11:57 pts/2 00:00:00 ps -ef roel 316500 316204 0 11:57 pts/2 00:00:00 grep -E 316204|PIDOder aus einem Skript heraus. Betrachten wir zum Beispiel das folgende
Skript test.sh:echo $$ ps -ef | grep -E "$$|PID"Was, wenn wir es ausführbar machen (
chmod +x test.sh) und ausführen, Folgendes erzeugt:chmod +x test.sh ./test.sh 316820 UID PID PPID C STIME TTY TIME CMD roel 316820 316204 0 12:01 pts/2 00:00:00 bash roel 316821 316820 0 12:01 pts/2 00:00:00 ps -ef roel 316822 316820 0 12:01 pts/2 00:00:00 grep -E 316820|PIDDer Unterschied liegt in der erzeugten PID! Das mag auf den ersten Blick konzeptionell sinnvoll sein, aber lassen Sie uns den Hauptgrund erklären, warum sich die PID unterscheidet: Wir verwenden eine andere Bash-Shell. Der erste ausgeführte Befehl erfolgte direkt auf der Kommandozeile, und daher erzeugt unsere spezielle Variable
$$(die die PID des aktuell laufenden Programms identifiziert) die PID der aktuell laufenden Bash-Shell (die 316204 ist).In der zweiten Instanz führen wir ein Skript aus und jeder Start eines Skripts startet immer eine neue Bash-Shell. Das Ergebnis ist, dass unsere PID die PID der neu gestarteten Bash-Shell (316820) ist. Wir können dies auch bestätigen, indem wir uns die PPID (d.h. die übergeordnete PID oder das übergeordnete Element der Prozesskennung) ansehen – es ist 316204, die mit unserer Bash-Shell übereinstimmt, von der aus wir das Skript gestartet haben, wie im ersten Beispiel zu sehen (sowohl das erste als auch das zweite Beispiel wurden im selben Terminal auf demselben Rechner ausgeführt).
Der Befehl
grep -Ein unseren beiden Beispielen ermöglicht es uns, die erste Zeile der vollständigen Prozessliste der Maschine (wie vonps -eferhalten) zu erfassen, indem wir neben unserer PID (mit$$) erweiterte Regex-Unterstützung und Grepping fürPIDzulassen. Das|ist das erweiterte Trennzeichen für reguläre Ausdrücke, das diese duale Erfassung ermöglicht.Weitere Informationen zu regulären Ausdrücken finden Sie in unseren Artikeln Bash-Regexps für Anfänger mit Beispielen und Fortgeschrittene Bash-Regex mit Beispielen.
Beachten Sie auch, dass wir die PID-Erfassung automatisiert haben, indem wir
$$imgrep-Befehlverwendet haben. Diese$$-Variable ändert sich nie, es sei denn, es wird eine neue Bash-Shell/Sub-Shell gestartet, wie wir im folgenden Beispiel sehen können:echo $$ 316204 bash echo $$ 318023 echo $PPID 316204Die PID unserer Bash-Hauptshell ist immer noch 316204 wie zuvor. Als nächstes starten wir eine neue Unterschale und die PID dieser neuen Schale wird bei der Überprüfung 318023. Und mit der automatisch gesetzten (von Bash) Variablen
$PPIDkönnen wir die PPID (Parent Process ID) der sekundären Bash-Shell/Sub-Shell als 316204 bestätigen, die mit unserer Haupt-Shell übereinstimmt. Wie Sie sehen können, gibt es in Bezug auf das Prozessmanagement und speziell die Variable$$keinen großen Unterschied zwischen dem Starten eines Skripts und einer neuen Subshell.Weitere Informationen zum Bash-Prozessmanagement finden Sie in unseren Artikeln Bash-Hintergrundprozessmanagement und Prozesslistenverwaltung und Automatische Prozessbeendigung.
$? – Exit-Code
Die Variable
$?teilt uns mit, wie der Exit-Code des vorherigen Befehls lautete. Wenn wir den Exit-Code einer ausgeführten Anweisung kennen, können wir ein Skript in zwei oder mehr verschiedene Richtungen fortsetzen. Wenn wir beispielsweise einenrm-Befehl(zum Löschen einiger Dateien) aus einem Programm heraus gestartet haben, möchten wir möglicherweise überprüfen, ob der Vorgang erfolgreich abgeschlossen wurde.Wenn der Exit-Code
0ist, bedeutet dies in der Regel (sprich: fast immer), dass ein Prozess erfolgreich beendet wurde. Wenn der Exit-Codejedoch 1(oder mehrere) ist, bedeutet dies oft (wenn auch nicht immer), dass der Prozess mit einem Fehler oder negativem Ergebnis beendet wurde, z. B. konnte die Datei in unserem Beispiel nicht gelöscht werden. Schauen wir uns an, wie dies auf der Befehlszeile funktioniert, wobei wir uns daran erinnern, dass die Funktionsweise dieser Variablen innerhalb eines Skripts identisch ist.touch this.exists rm this.exists echo $? 0 rm this.does.not.exist rm: cannot remove 'this.does.not.exist': No such file or directory echo $? 1Wir erstellen zuerst eine Datei
this.existsmit demTouch-Befehl.Toucherstellt einfach eine Datei mit der Größe Null, ohne etwas in sie zu schreiben. Als nächstes entfernen wir die Datei mitrm this.existsund zeigen den$?Exit-Code mitechoan. Das Ergebnis ist 0, da der Befehl wie erwartet erfolgreich war und kein Fehler zurückgegeben wird.Als nächstes versuchen wir, eine Datei zu löschen, die nicht existiert, und erhalten eine Fehlermeldung. Wenn wir den Exit-Code überprüfen, ist er tatsächlich
1, was darauf hinweist, dass ein Fehler aufgetreten ist. Wir können den Wert dieser Variablen leicht über die Befehlszeile oder innerhalb eines Skripts überprüfen, indem wir eineif [ $? -eq 0 ]; thenoder eine ähnliche bedingte Anweisung (beendet durchfi) verwenden.1 $, 2 $, ... $* – Argumente übergeben
Wenn wir ein Skript an der Bash-Befehlszeile starten, können wir Argumente an dasselbe übergeben. Es liegt ganz im Ermessen des Skripts, die an das Skript übergebenen Argumente zu verarbeiten. Wenn das Skript z. B. überhaupt keine Argumente verarbeitet (die Standardeinstellung), hat es keine Konsequenzen, wenn Sie in einem Skript eine oder mehrere Variablen angeben oder nicht angeben.
Wir können mit übergebenen Argumenten umgehen, indem wir die speziellen Variablen
$1,$2,$*usw. verwenden. Das erste Argument, das an das Skript übergeben wird, ist immer$1, das zweite Argument ist immer$2usw. Eine Sache, auf die Sie achten sollten, ist, dass, wenn Sie ein Leerzeichen in einem standardmäßig konfigurierten Bash-Client einführen, Bash dieses Leerzeichen als Trennzeichen interpretiert.Wenn Sie versuchen, einen Text zu übergeben, wie zum Beispiel
, dies ist ein Beispiel, müssten Sie ihn richtig zitieren, wie folgt:"Dies ist ein Beispiel";damit Bash diesen Text als eine einzelne Variable sieht, die übergeben wird.Die spezielle Variable
$*ist eine Abkürzung für das Schreiben aller Variablen in einen einzigen String. Sehen wir uns an, wie dies funktioniert, indem wir ein neuestest2.sh-Skriptwie folgt definieren:echo "1: ${1}" echo "2: ${2}" echo "All: ${*}"Als kleine Variation haben wir uns dafür entschieden, unsere Variablen hier als
$ {1}bis$ {*}anstelle von$1bis$*zu definieren. In der Tat wäre es eine gute Idee, Variablen immer auf diese Weise zu zitieren. Weitere Informationen finden Sie in unserem Artikel Korrektes Variablen-Parsing und Zitating in Bash.Wenn wir dasselbe mit zwei oder drei Argumenten ausführen, sehen wir:
chmod +x test2.sh ./test2.sh '1' '2' 1: 1 2: 2 All: 1 2 ./test2.sh '1' '2' '3' 1: 1 2: 2 All: 1 2 3Wir können sehen, wie unsere erste Eingabe in das Skript korrekt als
$1usw. erkannt wird. Außerdem stellen wir fest, dass das dritte Argument vom Skript vollständig ignoriert wird, bis es die Echo-Anweisung"All: $ {*}"erreicht, die tatsächlich alle Argumente anzeigt, wie zuvor besprochen. Schauen wir uns nun eine falsche Eingabe ohne Zitat an:./test2.sh This is meant to be a single sentence. 1: This 2: is All: This is meant to be a single sentence. ./test2.sh "This is meant to be a single sentence." 1: This is meant to be a single sentence. 2: All: This is meant to be a single sentence.Hier wird deutlich, wie ein Leerzeichen als Trennzeichen statt als tatsächliches Leerzeichen interpretiert werden kann, es sei denn, der Text wird richtig zitiert. Im ersten Ergebnis wird Dies als erstes Argument angesehen, während im zweiten Ergebnis der gesamte Satz als erstes Argument angesehen wird.
$0 – der Befehl, der ausgeführt
wirdNachdem man etwas über
$1gelernt hat, könnte man sich fragen, was die spezielle Variable\$0macht. Wenn Sie darüber nachdenken, wie ein Befehl gebildet wird (Befehl, Argument1, Argument2usw.), bemerken Sie vielleicht, dassder Befehlvor dem ersten Argument ($1) steht. Command ist also in gewisser Weise – visuell –\$0, und das ist genau das, was die spezielle Variable\$0enthält; Der Befehl wird ausgeführt.echo \$0 bashWie wir sehen können und wie es sinnvoll ist, ist der aktuell ausgeführte Befehl auf der Befehlszeile
bash. Wenn wir den Befehlecho \$0zu einem Testskripthinzufügen test3.shund ausführen, erhalten wir:./test3.sh ./test3.sh ../workspace/test3.sh ../workspace/test3.sh
Um mehr über if-basierte Anweisungen zu erfahren, lesen Sie bitte Bash If-Anweisungen If Elif Else Then Fi. Das Kombinieren von $? mit if-Anweisungen ist eine gängige und leistungsstarke Methode, um verschiedene Dinge in Bash zu automatisieren.
Wie bisher ist der aktuell laufende Befehl ./test3.sh, genau so, wie er von der Kommandozeile ausgeführt wird. Wenn wir den Befehl mit einem längeren Pfadnamen wie .. /workspace/test3.sh dann wieder wird dies über die spezielle Variable \$0 wiederholt.
Schlussfolgerung
In diesem Artikel haben wir die Variablen $$, $?, $1, $2 usw., $* und \$0 untersucht, wie sie funktionieren und wie Sie sie entweder direkt von der Befehlszeile oder aus Skripten heraus verwenden können. Es gibt noch ein paar andere spezielle Variablen, aber dies sind die wichtigsten speziellen Variablen in Bash, die ich in vielen Jahren der Bash-Codierung verwendet habe. Genießen!
