Der Zweck der Shell – das Ausführen von Befehlen – ist so grundlegend für Linux, dass man glauben könnte, die Shell wäre auf irgendeine besondere Weise in Linux eingebaut. Das ist sie aber nicht. Eine Shell ist auch nur ein normales Programm wie ls oder cat. Sie ist darauf programmiert, die folgenden Schritte immer und immer und immer wieder zu wiederholen:
Linux ist ziemlich gut darin, die Tatsache zu verbergen, dass eine Shell ein normales Programm ist. Wenn Sie sich anmelden, führt Linux automatisch eine Instanz der Shell für Sie aus, nämlich Ihre Login-Shell. Sie startet so nahtlos, dass sie Linux zu sein scheint, obwohl sie nur ein Programm ist, das in Ihrem Namen mit Linux interagiert.
Wo ist Ihre Login-Shell? Wenn Sie sich an einem nicht grafischen Terminal anmelden, etwa mit einem SSH-Clientprogramm, ist die Login-Shell die erste Shell, mit der Sie es zu tun haben. Sie gibt den ersten Prompt aus und wartet auf Ihre Befehle. Falls Sie alternativ an der Konsole Ihres Computers mit einer grafischen Anzeige sind, läuft die Shell hinter den Kulissen. Sie startet eine Desktopumgebung wie GNOME, Unity, Cinnamon oder KDE Plasma. Sie können dann Terminalfenster öffnen, um weitere interaktive Shells auszuführen. |
Je besser Sie die Shell verstehen, umso effektiver können Sie mit Linux arbeiten, und umso weniger Fehlannahmen entwickeln Sie über ihre inneren Abläufe. Dieses Kapitel untersucht die folgenden Mysterien der Shell gründlicher als Kapitel 2:
Ich hoffe, dass Sie am Ende herausgefunden haben, dass diese Mysterien gar nicht so mysteriös sind.
Die Standard-Shell auf den meisten Linux-Systemen ist bash,1 und diese ist ein normales Programm – eine ausführbare Datei –, das im Systemverzeichnis /bin neben cat, ls, grep und anderen vertrauten Befehlen zu finden ist:
$ cd /bin
$ ls -l bash cat ls grep
-rwxr-xr-x 1 root root 1113504 Jun 6 2019 bash
-rwxr-xr-x 1 root root 35064 Jan 18 2018 cat
-rwxr-xr-x 1 root root 219456 Sep 18 2019 grep
-rwxr-xr-x 1 root root 133792 Jan 18 2018 ls
Wahrscheinlich ist bash nicht die einzige Shell auf Ihrem System. Gültige Shells sind üblicherweise zeilenweise in der Datei /etc/shells aufgeführt:
$ cat /etc/shells
/bin/sh
/bin/bash
/bin/csh
/bin/zsh
Um festzustellen, welche Shell Sie ausführen, geben Sie mit echo die Shell-Variable SHELL aus:
$ echo $SHELL
/bin/bash
Theoretisch kann ein Linux-System jedes Programm als gültige Login-Shell behandeln, wenn ein Benutzer-Account so konfiguriert ist, dass er es als Login aufruft, und wenn es in /etc/shells aufgeführt ist (falls das auf Ihrem System erforderlich ist). Mit Superuser-Rechten können Sie sogar Ihre eigene Shell schreiben und installieren, siehe das Skript in Beispiel 6-1. Es liest jeden Befehl ein und antwortet dann: »Tut mir leid, aber ich kann das nicht machen.« Diese selbst gemachte Shell ist bewusst albern, aber sie demonstriert, dass andere Programme genauso rechtmäßige Shells sein können wie /bin/bash.
Beispiel 6-1: halshell: Eine Shell, die sich weigert, Ihre Befehle auszuführen
#!/bin/bash
# Gibt einen Prompt aus.
# Liest die Eingabe des Benutzers in einer Schleife.
# Beendet sich, wenn der Benutzer Strg-D drückt.
while read line; do
# Ignoriert die Eingabe $line und gibt eine Botschaft aus.
echo "Tut mir leid, aber ich kann das nicht machen"
# Gibt den nächsten Prompt aus.
echo -n '$ '
done
Da bash nur ein Programm ist, können Sie es wie jeden anderen Befehl manuell ausführen:
$ bash
Wenn Sie das machen, sehen Sie einfach einen weiteren Prompt, eben so, als hätte Ihr Befehl keine Wirkung gehabt:
$
In Wirklichkeit haben Sie eine neue Instanz von bash ausgeführt. Diese neue Instanz gibt einen Prompt aus und wartet auf Ihre Befehle. Um die neue Instanz besser sichtbar zu machen, ändern Sie ihren Prompt (etwa auf %%), indem Sie die Shell-Variable PS1 setzen und einige Befehle ausführen:
$ PS1="%% "
%% ls Der Prompt hat sich geändert.
animals.txt
%% echo "Dies ist eine neue Shell"
Dies ist eine neue Shell
Rufen Sie nun exit auf, um die neue Instanz von bash zu beenden. Sie kehren zur Original-Shell zurück, deren Prompt ein Dollarzeichen ist:
%% exit
$
Ich muss noch einmal darauf hinweisen, dass die Änderung von %% zurück zu $ keine Änderung des Prompts war. Stattdessen wurde die ganze Shell gewechselt. Die neue Instanz von bash wurde beendet, sodass nun die Original-Shell auf den nächsten Befehl wartet.
Das manuelle Ausführen von bash hat nicht nur Unterhaltungswert. Sie werden in Kapitel 7 Shells benutzen, die von Hand gestartet wurden.
Wenn eine Instanz der Shell eine andere aufruft, wie ich es gerade gezeigt habe, wird die Original-Shell Eltern und die neue Instanz Kind genannt. Das gilt für jedes Linux-Programm, das ein anderes Linux-Programm startet. Das startende Programm ist das Elternprogramm, und das gestartete Programm ist sein Kind. Ein laufendes Linux-Programm wird auch als Prozess bezeichnet, Ihnen werden also die Begriffe Elternprozess und Kindprozess begegnen. Ein Prozess kann eine beliebige Anzahl von Kindern aufrufen, aber jedes Kind hat nur einen Elternprozess.
Jeder Prozess besitzt seine eigene Umgebung. Eine Umgebung enthält, wie Sie vielleicht noch aus »Umgebungen und Initialisierungsdateien, die Kurzfassung« auf Seite 49 wissen, ein aktuelles Verzeichnis, einen Suchpfad, einen Shell-Prompt und andere wichtige Informationen, die in Shell-Variablen gespeichert sind. Wenn ein Kind erzeugt wird, ist seine Umgebung im Großen und Ganzen eine Kopie der Umgebung seines Elternprozesses. (Ich erkläre das genauer in »Umgebungsvariablen« auf Seite 121.)
Jedes Mal, wenn Sie einen einfachen Befehl ausführen, erzeugen Sie einen Kindprozess. Dies ist ein so wichtiger Punkt beim Verstehen von Linux, dass ich es noch einmal sage: Selbst wenn Sie einen einfachen Befehl wie ls ausführen, läuft dieser Befehl heimlich in einem neuen Kindprozess mit seiner eigenen (kopierten) Umgebung. Das bedeutet, dass alle Änderungen, die Sie in einem Kind vornehmen, wie das Ändern der Prompt-Variablen PS1 in einer Kind-Shell, nur das Kind beeinflussen und verloren gehen, wenn das Kind beendet wird. Entsprechend werden Kinder, die bereits laufen, nicht durch Änderungen beeinflusst, die Sie am Elternprozess durchführen. Solche Änderungen am Elternprozess können jedoch seine künftigen Kinder betreffen, da die Umgebung eines Kinds bei dessen Start eine Kopie der Elternumgebung ist.
Wieso ist es wichtig, dass Befehle in Kindprozessen laufen? Zum einen bedeutet es, dass jedes Programm, das Sie ausführen, mit cd irgendwo im Dateisystem landen kann, doch wenn es beendet wird, hat Ihre aktuelle Shell (der Elternprozess) sein aktuelles Verzeichnis nicht geändert. Zum Beweis kommt hier ein schnelles Experiment. Erzeugen Sie in Ihrem Home-Verzeichnis ein Shell-Skript namens cdtest, das den Befehl cd enthält:
#!/bin/bash
cd /etc
echo "Hier ist mein aktuelles Verzeichnis:"
pwd
Machen Sie es ausführbar:
$ chmod +x cdtest
Geben Sie Ihren aktuellen Verzeichnisnamen aus und rufen Sie dann das Skript auf:
$ pwd
/home/smith
$ ./cdtest
Hier ist mein aktuelles Verzeichnis:
/etc
Prüfen Sie nun Ihr aktuelles Verzeichnis:
$ pwd
/home/smith
Ihr aktuelles Verzeichnis hat sich nicht geändert, obwohl das cdtest-Skript zum Verzeichnis /etc gereist ist. Das liegt daran, dass cdtest in einem Kindprozess mit seiner eigenen Umgebung gelaufen ist. Änderungen an der Umgebung des Kinds haben keinen Einfluss auf die Umgebung des Elternprozesses, sodass sich auch das aktuelle Verzeichnis des Elternprozesses nicht geändert hat. Das Gleiche passiert auch, wenn Sie ein ausführbares Programm wie cat oder grep aufrufen – es läuft in einem Kindprozess, der beendet wird, wenn das Programm fertig ist, und alle Umgebungsänderungen mitnimmt.
Weshalb cd ein Shell-Builtin sein muss Wenn Linux-Programme das aktuelle Verzeichnis Ihrer Shell nicht ändern können, wie schafft es dann der Befehl cd, es zu ändern? Nun, cd ist kein Programm. Es ist eine in die Shell eingebaute Funktion (auch Shell-Builtin genannt). Wäre cd ein Programm außerhalb der Shell, wären Verzeichnisänderungen unmöglich – sie würden in einem Kindprozess laufen und könnten den Elternprozess nicht beeinflussen. |
Pipelines starten mehrere Kindprozesse: einen für jeden Befehl in der Pipeline. Dieser Befehl aus dem Abschnitt »Befehl #6: uniq« auf Seite 31 startet sechs Kinder:
$ cut -f1 grades | sort | uniq -c | sort -nr | head -n1 | cut -c9
Jede Instanz der Shell hat eine Sammlung an Variablen, wie Sie in »Variablen auswerten« auf Seite 39 gelernt haben. Manche Variablen sind lokal in einer einzigen Shell. Sie werden lokale Variablen genannt. Andere Variablen werden automatisch von einer bestimmten Shell in jedes Kind kopiert, das sie startet. Diese Variablen werden als Umgebungsvariablen bezeichnet, und sie bilden gemeinsam die Umgebung der Shell. Hier sind Beispiele für Umgebungsvariablen und ihre Einsatzgebiete:
HOME
Der Pfad zu Ihrem Home-Verzeichnis. Dessen Wert wird automatisch durch Ihre Login-Shell gesetzt, wenn Sie sich anmelden. Texteditoren wie vim und emacs lesen die Variable HOME, damit sie ihre Konfigurationsdateien finden und lesen können ($HOME/.vim bzw. $HOME/.emacs).
PWD
Das aktuelle oder auch Arbeitsverzeichnis Ihrer Shell. Dieser Wert wird automatisch durch Ihre Shell gesetzt und auf dem Laufenden gehalten, wann immer Sie mit cd in ein anderes Verzeichnis wechseln. Der Befehl pwd liest die Variable PWD, um den Namen des aktuellen Verzeichnisses Ihrer Shell auszugeben.
EDITOR
Der Name (oder der Pfad) Ihres bevorzugten Texteditors. Diesen Wert legen im Allgemeinen Sie selbst in einer Shell-Konfigurationsdatei fest. Andere Programme lesen dann diese Variable, um in Ihrem Namen einen passenden Editor zu starten.
Sie betrachten die Umgebungsvariablen einer Shell mit dem Befehl printenv. Die Ausgabe listet eine Variable pro Zeile auf. Sie ist unsortiert und kann recht lang ausfallen. Schicken Sie sie daher am besten mittels einer Pipeline durch sort und less, um das Betrachten angenehmer zu machen:2
$ printenv | sort -i | less
...
DISPLAY=:0
EDITOR=emacs
HOME=/home/smith
LANG=en_US.UTF-8
PWD=/home/smith/Music
SHELL=/bin/bash
TERM=xterm-256color
USER=smith
...
Lokale Variablen tauchen in der Ausgabe von printenv nicht auf. Sie zeigen deren Werte an, indem Sie vor den Variablennamen ein Dollarzeichen setzen und das Ergebnis mit echo ausgeben:
$ title="Efficient Linux"
$ echo $title
Efficient Linux
$ printenv title (erzeugt keine Ausgabe)
Um eine lokale Variable in eine Umgebungsvariable umzuwandeln, verwenden Sie den Befehlexport:
$ MY_VARIABLE=10 Eine lokale Variable.
$ export MY_VARIABLE Exportieren Sie diese, um eine Umgebungsvariable zu erhalten.
$ export ANOTHER_VARIABLE=20 Oder setzen und exportieren Sie sie in einem einzigen Befehl.
export legt fest, dass die Variable und ihr Wert aus der aktuellen Shell in künftige Kinder kopiert werden. Lokale Variablen dagegen werden nicht an Kindprozesse kopiert:
$ export E="Ich bin eine Umgebungsvariable" Setzen einer Umgebungsvariablen.
$ L="Ich bin nur eine lokale Variable" Setzen einer lokalen Variablen.
$ echo $E
Ich bin eine Umgebungsvariable
$ echo $L
Ich bin nur eine lokale Variable
$ bash Ausführen einer Kind-Shell.
$ echo $E Umgebungsvariable wurde kopiert.
Ich bin eine Umgebungsvariable
$ echo $L Lokale Variable wurde nicht kopiert.
Ein leerer String wird ausgegeben.
$ exit Beenden der Kind-Shell.
Merken Sie sich, dass die Variablen eines Kinds Kopien sind. Änderungen an der Kopie haben keine Auswirkungen auf die Eltern-Shell:
$ export E="Ich bin der Originalwert" Setzen einer Umgebungsvariablen.
$ bash Ausführen einer Kind-Shell.
$ echo $E
Ich bin der Originalwert Elternwert wurde kopiert.
$ E="Ich wurde in einem Kind modifiziert" Die Kopie des Kinds wird geändert.
$ echo $E
Ich wurde in einem Kind modifiziert
$ exit Beenden der Kind-Shell.
$ echo $E
Ich bin der Originalwert Elternwert ist unverändert.
Starten Sie eine neue Shell und ändern Sie irgendetwas in deren Umgebung. Sobald Sie die Shell beenden, verschwinden auch die Änderungen. Das bedeutet, dass Sie sicher mit Shell-Eigenschaften experimentieren können – rufen Sie einfach manuell eine Shell auf, wodurch Sie ein Kind erzeugen, und beenden Sie sie, wenn Sie fertig sind.
Manchmal verbirgt Linux seine inneren Abläufe zu gut. Ein Beispiel dafür ist das Verhalten von Umgebungsvariablen. Irgendwie, fast wie durch Zauberei, weisen Variablen wie HOME und PATH in all Ihren Shell-Instanzen einen konsistenten Wert auf. Sie scheinen in gewisser Weise »globale Variablen« zu sein. (Ich habe diese Behauptung sogar schon in anderen Linux-Büchern gesehen, zum Glück allerdings nicht in O’Reilly-Büchern.) Eine Umgebungsvariable ist aber nicht global. Jede Shell-Instanz hat ihre eigene Kopie. Das Modifizieren einer Umgebungsvariablen in einer Shell kann den Wert in anderen laufenden Shells nicht verändern. Modifikationen beeinflussen nur künftige Kinder dieser Shell (die also noch nicht gestartet wurden).
Wenn das der Fall ist, wieso scheint dann eine Variable wie HOME oder PATH ihren Wert in all Ihren Shell-Instanzen beizubehalten? Es gibt zwei Wege, um das zu ermöglichen, die in Abbildung 6-1 dargestellt werden. Kurz gesagt:
Kinder kopieren von ihren Eltern.
Für Variablen wie HOME werden die Werte normalerweise durch Ihre Login-Shell gesetzt und exportiert. Alle künftigen Shells (bis Sie sich abmelden) sind Kinder der Login-Shell, sie erhalten also eine Kopie der Variablen und ihres Werts. Diese Arten von systemdefinierten Umgebungsvariablen werden im echten Leben so selten modifiziert, dass sie global zu sein scheinen. Dabei sind es ganz normale Variablen, die nach ganz normalen Regeln spielen. (Sie könnten ihre Werte in einer laufenden Shell sogar ändern, aber das könnte das erwartete Verhalten dieser Shell und anderer Programme stören.)
Unterschiedliche Instanzen lesen dieselben Konfigurationsdateien.
Die Werte lokaler Variablen, die nicht an Kinder kopiert werden, können in einer Linux-Konfigurationsdatei wie etwa $HOME/.bashrc gesetzt werden (Näheres in »Ihre Umgebung konfigurieren« auf Seite 125). Jede Instanz der Shell liest beim Start die entsprechenden Konfigurationsdateien und führt sie aus. In der Folge scheinen diese lokalen Variablen von Shell zu Shell kopiert zu werden. Das gilt auch für andere nicht exportierte Shell-Eigenschaften wie Aliase.
Dieses Verhalten versetzt einige Benutzer in den Irrglauben, dass der export-Befehl eine globale Variable erzeugt. Das macht er nicht. Der Befehl export WHATEVER erklärt lediglich, dass die Variable WHATEVER von der aktuellen Shell in künftige Kinder kopiert wird.
Abbildung 6-1: Shells können Variablen und Werte durch einen Export teilen oder indem sie dieselben Konfigurationsdateien lesen.
Ein Kind ist eine teilweise Kopie seiner Elterninstanz. Es enthält zum Beispiel Kopien der Eltern-Umgebungsvariablen, aber nicht der lokalen (nicht exportierten) Variablen oder Aliase:
$ alias Auflisten der Aliase.
alias gd='pushd'
alias l='ls -CF'
alias pd='popd'
$ bash --norc Ausführen einer Kind-Shell und Ignorieren der bashrc-Dateien.
$ alias Auflisten der Aliase - es sind keine bekannt.
$ echo $HOME Umgebungsvariablen sind bekannt.
/home/smith
$ exit Beenden der Kind-Shell.
Sollten Sie sich jemals gefragt haben, wieso Ihre Aliase in Shell-Skripten nicht verfügbar sind, dann wissen Sie jetzt, warum. Shell-Skripte laufen in einem Kind, das keine Kopien der Eltern-Aliase erhält.
Eine Subshell ist im Gegensatz dazu eine komplette Kopie ihrer Eltern-Shell.3 Sie enthält alle Variablen, Aliase, Funktionen und mehr der Eltern-Shell. Um einen Befehl in einer Subshell zu starten, schließen Sie ihn in runde Klammern ein:
$ (ls -l) Startet ls -l in einer Subshell.
-rw-r--r-- 1 smith smith 325 Oct 13 22:19 animals.txt
$ (alias) Betrachtet Aliase in einer Subshell.
alias gd=pushd
alias l=ls -CF
alias pd=popd
...
$ (l) Führt einen Alias der Eltern-Shell aus.
animals.txt
Um zu überprüfen, ob eine Shell-Instanz eine Subshell ist, geben Sie die Variable-BASH_SUBSHELL aus. Der Wert ist in Subshells ungleich null, ansonsten ist er null:
$ echo $BASH_SUBSHELL Prüfen der aktuellen Shell
0 keine Subshell
$ bash Ausführen einer Kind-Shell
$ echo $BASH_SUBSHELL Prüfen der Kind-Shell
0 keine Subshell
$ exit Beenden der Kind-Shell
$ (echo $BASH_SUBSHELL) Ausführen einer expliziten Subshell
1 Ja, es ist eine Subshell.
Ich werde in »Technik #10: Explizite Subshells« auf Seite 151 einige praktische Anwendungen von Subshells behandeln. Seien Sie sich für den Augenblick nur bewusst, dass Sie sie erzeugen können und dass sie die Aliase ihrer Eltern-Shell kopieren.
Wenn die bash läuft, konfiguriert sie sich selbst, indem sie eine Abfolge von Dateien, die sogenannten Konfigurationsdateien, liest und deren Inhalt ausführt. Diese Dateien definieren Variablen, Aliase, Funktionen und andere Shell-Eigenschaften und können auch Linux-Befehle enthalten. (Sie sind wie Shell-Skripte, die die Shell konfigurieren.) Manche Konfigurationsdateien werden durch den Systemadministrator definiert und gelten systemweit für alle Anwender. Sie sind im Verzeichnis /etc zu finden. Andere Konfigurationsdateien gehören den einzelnen Benutzern und werden auch von diesen geändert. Sie befinden sich im Home-Verzeichnis des jeweiligen Benutzers. Tabelle 6-1 listet die Standardkonfigurationsdateien der bash auf, von denen es verschiedene Typen gibt:
Startdateien
Konfigurationsdateien, die automatisch ausgeführt werden, wenn Sie sich anmelden – das heißt, sie gelten nur in Ihrer Login-Shell. Ein Befehl in dieser Datei könnte zum Beispiel eine Umgebungsvariable setzen und exportieren. Das Definieren eines Alias in dieser Datei wäre dagegen nicht so sinnvoll, weil Aliase nicht an Kinder kopiert werden.
Initialisierungsdateien (init)
Konfigurationsdateien, die für jede Shell-Instanz ausgeführt werden, die keine Login-Shell ist – etwa wenn Sie eine interaktive Shell von Hand oder über ein (nicht interaktives) Shell-Skript ausführen. Ein Befehl in einer Initialisierungsdatei könnte zum Beispiel eine Variable setzen oder einen Alias definieren.
Cleanup-Dateien
Konfigurationsdateien, die unmittelbar vor dem Beenden Ihrer Login-Shell ausgeführt werden. Ein Befehl in dieser Datei könnte zum Beispiel clear sein, der Ihren Bildschirm beim Ausloggen löscht.
Tabelle 6-1: Standardkonfigurationsdateien, die von der bash geladen werden
Sie sehen sicher, dass Sie drei Möglichkeiten für persönliche Startdateien in Ihrem Home-Verzeichnis haben (.bash_profile, .bash_login und .profile). Die meisten Benutzer entscheiden sich nur für eine und bleiben dann bei dieser. Ihre Linux-Distribution bringt vermutlich bereits eine mit, in der sich (idealerweise) schon nützliche Befehle befinden. Ein bisschen anders sieht es aus, wenn Sie andere Shells ausführen, wie etwa die Bourne-Shell (/bin/sh) und die Korn-Shell (/bin/ksh). Diese Shells lesen ebenfalls .profile und machen möglicherweise Probleme (starten zum Beispiel nicht), wenn sie auf bash-spezifische Befehle treffen. Setzen Sie bash-spezifische Befehle deshalb stattdessen in .bash_profile oder .bash_login (auch hier sollten Sie sich für eine Datei entscheiden).
Manchmal finden Benutzer die Trennung zwischen persönlichen Startdateien und der persönlichen Initialisierungsdatei verwirrend. Warum sollte man wollen, dass sich Ihre Login-Shell anders verhält als Shells, die Sie zum Beispiel in mehreren Fenstern öffnen? Die Antwort lautet, dass es oft gar nicht nötig ist, dass sie sich anders verhalten. Ihre persönliche Startdatei macht vielleicht nicht mehr, als Ihre persönliche Initialisierungsdatei $HOME/.bashrc zu laden, sodass alle interaktiven Shells (Login oder Nichtlogin) im Großen und Ganzen die gleiche Konfiguration haben würden.
In anderen Fällen ziehen Sie es möglicherweise vor, die Verantwortung zwischen Ihren Start- und Initialisierungsdateien aufzuteilen. So könnte zum Beispiel Ihre persönliche Startdatei Ihre Umgebungsvariablen setzen und exportieren, die an künftige Kinder kopiert werden sollen, während $HOME/.bashrc all Ihre Aliase definiert (die nicht an die Kinder kopiert werden).
Eine weitere Überlegung ist, ob Sie sich in eine grafische Desktopumgebung mit Fenstern einloggen (GNOME, Unity, KDE Plasma usw.), in der Ihre Login-Shell verborgen ist. In diesem Fall dürfte es Ihnen egal sein, wie sich die Login-Shell verhält, weil Sie nur mit deren Kindern interagieren. Sie müssen dann also die Konfiguration teilweise oder ganz in $HOME/.bashrc legen.4 Falls Sie sich andererseits hauptsächlich von einem nicht grafischen Terminalprogramm aus einloggen, wie einem SSH-Client, können Sie direkt mit Ihrer Login-Shell interagieren, sodass deren Konfiguration eine viel größere Rolle spielt.
In jedem dieser Fälle lohnt es sich im Allgemeinen, durch Ihre persönliche Startdatei Ihre persönliche Initialisierungsdatei laden zu lassen:
# Setzen Sie dies in $HOME/.bash_profile oder eine andere persönliche Startdatei.
if [ -f "$HOME/.bashrc" ]
then
source "$HOME/.bashrc"
fi
Was auch immer Sie tun, versuchen Sie nicht, identische Konfigurationsbefehle in zwei unterschiedliche Konfigurationsdateien zu setzen. Das stiftet nur Verwirrung und ist schwer zu warten, da Sie daran denken müssen, jede Änderung, die Sie an einer Datei vornehmen, in der anderen zu duplizieren (und Sie werden das irgendwann vergessen, glauben Sie mir). Laden Sie stattdessen eine Datei aus der anderen, wie ich es Ihnen gezeigt habe.
Wenn Sie eine Start- oder Initialisierungsdatei ändern, können Sie eine laufende Shell zwingen, sie erneut einzulesen, wie ich in »Umgebungen und Initialisierungsdateien, die Kurzfassung« auf Seite 49 erklärt habe:
$ source ~/.bash_profile Verwendet das Builtin "source" command.
$ . ~/.bash_profile Verwendet einen Punkt.
Wieso der source-Befehl existiert Warum laden Sie eine Konfigurationsdatei mit dem source-Befehl, anstatt sie mit einem chmod ausführbar zu machen und wie ein Shell-Skript auszuführen? Weil ein Skript in einem Kindprozess ausgeführt wird. Die Befehle in dem Skript haben keine Auswirkungen auf die vorgesehene (Eltern-)Shell. Sie würden nur das Kind beeinflussen, das beendet wird, sodass Sie am Ende nichts verändert hätten. |
Falls Sie viele Linux-Maschinen an unterschiedlichen Orten benutzen, wollen Sie vermutlich irgendwann Ihre sorgfältig zusammengestellten Konfigurationsdateien auf mehr als einer Maschine installieren. Kopieren Sie nicht einzelne Dateien von Rechner zu Rechner – das führt nur irgendwann zu Verwirrung. Speichern und pflegen Sie die Dateien stattdessen auf einem freien und kostenlosen Account auf GitHub (https://github.com) oder einem vergleichbaren Softwareentwicklungsdienst mit Versionskontrolle. Sie können dann Ihre Konfigurationsdateien bequem und konsistent auf alle Ihre Linux-Maschinen herunterladen und sie dort installieren und aktualisieren. Sollten Sie beim Bearbeiten einer Konfigurationsdatei einen Fehler machen, können Sie mit nur wenigen Befehlen zu einer früheren Version zurückkehren. Das Behandeln der Versionskontrolle würde den Rahmen dieses Buchs sprengen; lesen Sie »Versionskontrolle für alltägliche Dateien« auf Seite 219, wenn Sie mehr wissen wollen.
Falls Sie mit Versionskontrollsystemen wie Git oder Subversion nicht zurechtkommen, speichern Sie die Konfigurationsdateien in einem einfachen Dateidienst wie Dropbox, Google Drive oder OneDrive. Updates Ihrer Konfigurationsdateien werden dann weniger bequem verlaufen, aber zumindest sind die Dateien leicht verfügbar, um sie auf andere Linux-Systeme zu kopieren.
Ich habe viele Linux-Anwender kennengelernt, denen Eltern- und Kindprozesse, Umgebungen und die Aufgaben der vielen Shell-Konfigurationsdateien irgendwie rätselhaft waren (oder die davon gar nichts wussten). Nach dem Lesen dieses Kapitels haben Sie hoffentlich ein klareres Bild von all diesen Dingen. Wir kommen in-Kapitel 7 auf sie zurück, wenn sie uns als leistungsstarke Werkzeuge zum flexiblen Ausführen von Befehlen dienen.