Wie Sie vermuten, hängt das genaue Verhalten von der Shell ab, POSIX legt jedoch eine grundlegende Funktionalität fest.
Die Befehlssuche und -ausführung für die Standard-Shell-Befehlssprache (von der die meisten Shells eine Obermenge implementieren) hat viele Fälle, aber wir sind im Moment nur an dem Fall interessiert, in dem sie PATH
verwendet wird. In diesem Fall:
Der Befehl muss mithilfe der Umgebungsvariablen PATH durchsucht werden, wie unter XBD-Umgebungsvariablen beschrieben
und
Wenn die Suche erfolgreich ist:
[...]
die Schale führt die Anwendung in einer unterschiedlichen Gebrauchsumgebung mit Aktionen , die äquivalent zu nennen execl()
Funktion [...] mit dem Pfad Argument Satz zu dem Pfadnamen aus der Suche ergibt.
Im erfolglosen Fall schlägt die Ausführung fehl und ein Exit-Code von 127 wird mit einer Fehlermeldung zurückgegeben.
Dieses Verhalten stimmt insbesondere mit der execvp
Funktion überein . Alle exec*
Funktionen akzeptieren den Dateinamen eines auszuführenden Programms, eine Folge von Argumenten (die argv
das Programm sein werden) und möglicherweise eine Reihe von Umgebungsvariablen. Für die Versionen, die PATH
Lookup verwenden, definiert POSIX Folgendes :
Die Argumentdatei wird verwendet, um einen Pfadnamen zu erstellen , der die neue Prozessabbilddatei [...] identifiziert. Das Pfadpräfix für diese Datei wird durch Durchsuchen der als Umgebungsvariable PATH übergebenen Verzeichnisse ermittelt
Das Verhalten von PATH wird an anderer Stelle definiert als:
Diese Variable muss die Folge von Pfadpräfixen darstellen, die bestimmte Funktionen und Dienstprogramme bei der Suche nach einer ausführbaren Datei anwenden, die nur unter einem Dateinamen bekannt ist. Die Präfixe werden durch ein <colon> (':') getrennt. Wenn auf diesen Dateinamen ein Präfix ungleich Null angewendet wird, wird zwischen dem Präfix und dem Dateinamen ein <Slash> eingefügt, wenn das Präfix nicht mit endet. Ein Präfix mit der Länge Null ist eine Legacy-Funktion, die das aktuelle Arbeitsverzeichnis angibt. Es wird als zwei benachbarte Zeichen ("::") angezeigt, als erstes <colon> vor dem Rest der Liste oder als nachfolgendes <colon> nach dem Rest der Liste. Eine streng konforme Anwendung muss einen tatsächlichen Pfadnamen (z. B..) Verwenden, um das aktuelle Arbeitsverzeichnis in PATH darzustellen.Die Liste wird von Anfang bis Ende durchsucht, wobei der Dateiname auf jedes Präfix angewendet wird, bis eine ausführbare Datei mit dem angegebenen Namen und den entsprechenden Ausführungsberechtigungen gefunden wird . Wenn der gesuchte Pfadname einen <Slash> enthält, wird die Suche durch die Pfadpräfixe nicht durchgeführt. Wenn der Pfadname mit einem <Slash> beginnt, wird der angegebene Pfad aufgelöst (siehe Pfadnamenauflösung ). Wenn PATH nicht gesetzt oder auf null gesetzt ist, ist die Pfadsuche implementierungsdefiniert.
Das ist ein bisschen dicht, also eine Zusammenfassung:
- Wenn der Programmname einen
/
(Schrägstrich, U + 002F SOLIDUS) enthält, behandeln Sie ihn wie gewohnt als Pfad und überspringen Sie den Rest dieses Vorgangs. Für die Shell tritt dieser Fall technisch nicht auf (da sich die Shell-Regeln bereits damit befasst haben).
- Der Wert von
PATH
wird an jedem Doppelpunkt in Stücke aufgeteilt und dann jede Komponente von links nach rechts verarbeitet. Als spezieller (historischer) Fall wird eine leere Komponente einer nicht leeren Variablen als .
(das aktuelle Verzeichnis) behandelt.
- Für jede Komponente wird der Programmname mit einer Verknüpfung an das Ende angehängt,
/
und das Vorhandensein einer Datei mit diesem Namen wird überprüft. Wenn eine vorhanden ist, werden auch gültige Ausführungsberechtigungen (+ x) überprüft. Wenn eine dieser Prüfungen fehlschlägt, fährt der Prozess mit der nächsten Komponente fort. Andernfalls wird der Befehl in diesen Pfad aufgelöst und die Suche abgeschlossen.
- Wenn Ihnen die Komponenten ausgehen, schlägt die Suche fehl.
- Wenn nichts
PATH
drin ist oder es nicht existiert, mach was du willst.
Echte Shells verfügen über integrierte Befehle, die vor dieser Suche gefunden werden, und häufig auch über Aliase und Funktionen. Die interagieren nicht mit PATH
. POSIX definiert einige Verhaltensweisen in Bezug auf diese , und Ihre Shell kann viel mehr haben.
Während es möglich ist, sich auf exec*
für Sie die meisten , dies zu tun, kann die Schale in die Praxis umzusetzen diese Lookup selbst, insbesondere Zwecke für das Caching, aber die leeren Cache - Verhalten ähnlich sein sollte. Muscheln haben hier einen ziemlich weiten Spielraum und in den Eckfällen ein subtil unterschiedliches Verhalten.
Wie Sie festgestellt haben, verwendet Bash eine Hash-Tabelle , um die vollständigen Pfade der zuvor angezeigten Befehle zu speichern, und auf diese Tabelle kann mit der hash
Funktion zugegriffen werden. Wenn Sie zum ersten Mal einen Befehl ausführen, der durchsucht wird, und wenn ein Ergebnis gefunden wird, wird es der Tabelle hinzugefügt, sodass Sie beim nächsten Versuch nicht mehr nachsehen müssen.
In zsh hingegen wird im PATH
Allgemeinen nach dem vollständigen Wert gesucht, wenn die Shell gestartet wird. Eine Nachschlagetabelle wird mit allen erkannten Befehlsnamen vorab ausgefüllt, sodass Laufzeitsuchen normalerweise nicht erforderlich sind (es sei denn, ein neuer Befehl wird hinzugefügt). Sie können dies feststellen, wenn Sie versuchen, einen Befehl zu vervollständigen, der zuvor nicht vorhanden war.
Sehr leichte Shells dash
delegieren in der Regel so viel Verhalten wie möglich an die Systembibliothek und müssen sich nicht an frühere Befehlspfade erinnern.
PATH
zwischenbash
undzsh
hilft mir, meine Verwirrung zu lösen!