Bash und Z Shell
Sowohl Bash als auch Z Shell lesen beim Starten eine Reihe von Dateien und führen die darin enthaltenen Kommandos aus. Dies ermöglich eine auf verschiedene Situationen angepasste Konfiguration.
Die Startdateien von Bash und Z Shell
Bash und Z Shell bieten beide ähnliche Möglichkeiten zur Konfiguration der jeweiligen Shell beim Starten. Hier erfahrt Ihr etwas über Gemeinsamkeiten und Unterschiede der beiden Shells.
login oder nicht login shell
Abhängig davon, wie eine Shell aufgerufen wird, werden beim Starten unterschiedliche Dateien eingelesen und ausgeführt. Um häufige Fehler zu vermeiden, ist es wichtig, diese Unterschiede zu kennen und zu verstehen. Benutzer von Mac OS X wundern sich z.B. häufig darüber, warum Ihre in X11 gestarteten xterm Sitzungen nicht so funktionieren, wie sie vom Programm Terminal her gewohnt sind. Diese Frage werden wir gleich klären.
Im Wesentlichen gibt es vier wichtige Unterscheidungen die wir treffen müssen:
- ist es eine login shell?
- ist es eine interactive shell?
- ist es eine restricted shell?
- mit welchem Namen wurde die Shell aufgerufen?
Die ersten beiden Fragen sind entscheidend dafür, welche Dateien die Shells beim Starten ausführen. Die o.g. Unterschiede zwischen Terminal und xterm unter Mac OS X kommen daher, dass Terminal eine login shell startet, während in xterm eine nicht login shell ausgeführt wird. Aus diesem Grund werden beim Starten unterschiedliche Dateien eingelesen, was zu einer unterschiedlichen Abrbeitsumgebung führt. Häufigstes Problem ist dabei, dass wichtige Variablen (wie z.B. die PATH Variable) nicht erwartungsgemäß gesetzt werden.
Wichtig:
Es ist entscheidend, dass wir uns bewusst machen, in welcher Reihenfolge die Startedateien ausgeführt werden, da später aufgerufene Kommandos u.U. den Effekt von füheren überschreiben.
Der Startvorgang der Bash
Eine Bash ist dann eine login shell, wenn das erste Zeichen, des ersten Arguments ($argv[0]) ein - ist oder wenn sie mit der Option --login gestartet wurde.
Eine Bash ist dann interaktiv, wenn sie ohne Argumente gestartet wurde, die keine Optionen sind und wenn sie nicht mit der -c Option gestartet wurde. "standard input" und "standard error" sind jeweils mit Terminals verbunden. Eine Bash ist auch dann eine "interactive shell", wenn sie mit der Option -i gestartet wurde. PS1 ist grundsätzlich gesetzt und die Variable $- enthält i.
Nachdem wir diese etwas trockenen Definitionen gelesen haben, nehmen wir noch zur Kenntnis, dass unter Mac OS X in Terminal normalerweise eine login shell läuft, während in X11 keine login shell gestartet wird. In beiden Fällen erhalten wir eine interaktive Shell. In Skripts laufen in aller Regel nicht interaktive Shells. Wird eine der weiter unten aufgeführten Dateien gefunden, ist aber nicht lesbar, gibt die Bash einen Fehler aus. Wird eine Datei nicht gefunden, passiert gar nichts. Aus Gründern der Einfachheit verzichte ich darauf, dies bei jeder Datei immer wieder zu erwähnen.~ wird (in der Regel) zum Heimverzeichnis des Benutzers expandiert.
Wenn bash als interaktive login shell aufgerufen wird oder als nicht interaktive Shell mit der --login Option, liest sie als erstes die Datei /etc/profile und führt sie zeilenweise aus. Dannach sucht sie der Reihe nach anch den Dateien ~/.bash_profile, ~/.bash_login und ~/.profile und führt die darin enthaltenen Kommandos aus. Dieses Verhalten kann durch den Aufruf mit der Option --noprofile unterdrückt werden.
Beim (sauberen) Beenden liest eine login shell die Kommandos in ~/.bash_logout und führt sie aus.
Eine interactive shell, die keine login shell ist, führt die Datei ~/.bashrc aus.
Hinweis:
In diese Datei schreiben Mac OS X Benutzer die Kommanods für die Konfiguration Ihrer Shellumgebung in xterm. Möchte man in xterm die selbe Umgebung haben wie im Terminal, kan man den Inhalt der ~/.bash_profile (oder eine anderen Konfigurationsdatei) mit dem source Kommando einlesen und erspart es sich so, zwei getrennte Dateien pflegen zu müssen.
Das Einlesen der ~/.bashrc Datei kann man durch Verwenden der Option --norc verhindern. Die Option --rcfile file veranlasst die Bash anstelle von ~/.bashrc die Datei file zu verarbeiten.
Wird die Bash als nicht interaktive Shell aufgerufen, etwa in Form eines Shell Skriptes, expandiert sie den Inhalt der Variablen $BASH_ENV. der expandierte Wert der Variablen wird als Dateiname interpretiert, denn die bash versucht einzulesen und auszuführen. Die PATH-Variable wird aber bei der Suche nach der Datei nicht berücksichtigt.
Ich habe mich hier auf die wichtigsten Aspekte des Startvorgangs beschränkt, um die Übersichtlichkeit zu gewährleisten. Wer an weiteren Informationen interessiert ist, kann sämtliche Details in der manpage zur Bash nachlesen.
Der Startvorgang der Z Shell (zsh)
Die Startprozedur der Z Shell (zsh) hat einige Gemeinsamkeiten mit dem Startvorgang der Bash, aber auch Unterschiede. Eine Z Shell ist eine login shell, wenn die Option -l gesetzt ist oder wenn (wie bei der Bash) das erste Zeichen der $argv[0] Variablen ein - ist. Die Variable $argv[0] enthält das erste beim Kommandoaufruf übergebene Argument.
Eine Z Shell (zsh) ist interaktiv, wenn die Option -i gesetzt ist. Diese wird bei der Initialisierung gesetzt, wenn standard input ein Terminal ist und Kommandos von standard input werden. Bis hierhin gibt es also keinen wesentlichen Unterschied zur Bash. Auch x werden von der Z Shellnicht vorhandene Dateien übersprungen, worauf ich aber nicht jedes mal erneut hinweisen werde.
Wenn eine Z Shell startet, werden zuerst Komamndos aus der Datei/etc/zshenv ausgeführt. Dies kann nicht umgangen werden. Das nachfolgende Verhalten kann durch die Optionen RCS und GLOBAL_RCS beeinflusst werden. Ich gehe hier aber nur auf das Standardverhalten ein.
Als nächstes wird die Datei $ZDOTDIR/.zshenv verarbeitet. Wenn die Shell eine login shell ist, kommt danach die Dateien /etc/zprofile und ZDOTDIR/.zprofile ans die Reihe. Ist die Shell interaktiv werden außerdem noch die Dateien /etc/zshrc und $ZDOTDIR//.zshrc ausgewertet. Schließlich werden noch für denn Fall, dass es sich um eine login shell handelt die Dateien /etc/zlogin und $ZDOTDIR/.zlogin gelesen und ausgeführt.
Wenn eine Z Shell terminiert, werden die Dateien $ZDOTDIR/.zlogout und /etc/zlogout gelesen. Dies geschieht sowohl beim Beenden mit dem exit oder dem logout Kommando als auch beim Lesen des EOF Zeichens vom Terminal (unter Mac OS X i.d.R. ctrl-D, nicht jedoch wenn die Shell durch Ausführen eines anderen Prozesses terminiert. Auch hier spilene die Optionen RSC und GLOABAL_RSC eine Rolle, auf die ich hier allerdings nicht im Detail eingehen möchte. Nur soviel: Wenn RSC nicht gesetzt ist, werden beim exit der Shell keine history Dateien geschreiben.
Einige Hinweise:
Wenn $ZDOTDIR nicht gesetzt ist, wird stattdessen $HOME verwendet (was bei den meisten von Euch die Regel sein dürfte). Anstelle von /etc kann bei der Installation der Z Shell auch ein anderes Verezichnis vorgegeben werden.
Da die Datei /etc/zshenv von allen Instanzen der zsh ausgeführt wird, ist es sinnvoll, diese Datei so knapp wie möglich zu halten. Die manpage empfiehlt insbesondere Code, der nicht in jeder einzelnen Shell ausgeführt werden soll, in einem Test der Form if [[ -o rcs ]]; then ... zu verpacken, damit er nicht ausgeführt wird, wenn die Shell mit der Option -f aufgerufen wird.
Einen kurzen Hinweis möchte ich noch darauf geben, dass alle genannten Dateien mit dem zsh builtin zcompile vorkompiliert werden können. Weitere Details findet Ihr in zshbuiltins(1).
So, ich hoffe Euch ist nun auch der Startprozess der Z Shell etwas klarer geworden. Weiterhin viel Spass mit der Shell und Fröhliches Skripten.