Wann wird $ PATH bei der Verwendung der Shell konsultiert?

1

Manchmal muss ich einen vollständigen Pfad angeben, da $ PATH anscheinend nicht konsultiert wird:

####            I have `virtualenv` and it's on my path            ####

$ virtualenv --version      # `virtualenv` is on my path
1.7.1.2
$ which virtualenv          # further details
/usr/bin/virtualenv
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

####               However, I can't `stat virtualenv`:             ####

$ stat virtualenv
stat: cannot stat `virtualenv': No such file or directory

####              I have to use `stat `which $BINARY``               ####

$ stat `which virtualenv`
  File: `/usr/bin/virtualenv'
  Size: 54              Blocks: 8          IO Block: 4096   regular file
Device: ca01h/51713d    Inode: 22860       Links: 1
Access: (0755/-rwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2012-11-28 23:48:03.919400541 -0500
Modify: 2012-04-23 06:34:09.000000000 -0400
Change: 2012-11-28 17:24:31.335400569 -0500
 Birth: -
$ 

Warum muss ich verwenden, which virtualenvwenn es auf meinem Weg ist?

Dmitry Minkovsky
quelle
1
Ich erhalte die gleichen Ergebnisse wie Sie auf meiner Box. Leider weiß ich nicht, warum das passiert.
slafat01

Antworten:

5

$PATHwird nur bei der Ausführung von Befehlen abgefragt . Wenn die Shell nach einem auszuführenden Befehl suchen muss, durchsucht $PATHsie die Liste der Verzeichnisse in $PATHund wählt die erste ausführbare Datei (mit einem entsprechenden Ausführungsbit in den Berechtigungen) aus, die dem angegebenen Namen entspricht, und führt sie aus.

Wenn Sie ausführen stat virtualenv, übergeben Sie virtualenvdem statProgramm ein Argument . Vorausgesetzt, dass states in C geschrieben ist, sieht es dann virtualenvals Argument in der Hauptmethode des Programms:

int main(int argc, char** argv)

Das argventhält zwei Elemente: index 0 ist der Befehl, mit dem Sie das Programm selbst aufrufen, also "stat". index 1 ist das erste Befehlszeilenargument, also "virtualenv".

Dies liegt daran, exec()dass Sie bei einer Reihe von Systemaufrufen (schauen Sie in der Manpage nach, wenn Sie neugierig sind) eine Reihe von Befehlszeilenargumenten übergeben können, wenn Sie den aktuellen Prozess durch einen untergeordneten Prozess ersetzen. Die Shell ruft eine Variante von auf exec()und analysiert Ihre Befehlszeile, um zu bestimmen, als welches Befehlszeilenargumentarray übergeben werden soll argv.

Da statnicht bekannt ist, ob es sich bei der von Ihnen angegebenen Datei um eine normale Datei, einen Symlink, einen Hardlink, eine ausführbare Datei oder ein Verzeichnis usw. handelt, wird nicht gesucht $PATH, um sie zu finden. Das übergebene Argument wird so behandelt, als würde es genau angeben, ${PWD}/virtualenvwo ${PWD}es zum Zeitpunkt des statProgrammaufrufs zum aktuellen Arbeitsverzeichnis erweitert wurde. Dies nennt man einen relativen Pfad .

Fast alle Befehle , die relative Pfade für Dateinamen als Argument akzeptieren , nicht suchen $PATH, obwohl ein paar Befehle tun könnte so, wie bashoder sshwenn Sie ihnen sagen , einen Befehl in der Kind - Shell - Umgebung auszuführen. Es hindert keinen beliebigen Befehl daran, eine bestimmte Umgebungsvariable nach der von Ihnen angegebenen Datei abzusuchen, sondern es handelt sich um ein anwendungsspezifisches Verhalten. Es würde überhaupt keinen Sinn machen, nach $PATHrelativen Pfaden zu suchen , da $PATHes sich nur um ausführbare Dateien handelt.

allquixotic
quelle
Genial. Vielen Dank, dass Sie die C- und Systemaufrufausführungserzählung integriert haben.
Dmitry Minkovsky
3

Das PATHwird benötigt und konsultiert, wenn Sie versuchen, etwas auszuführen.

Im Gegensatz zu Windows müssen Sie unter Unix immer ausführbare Dateien mit einem Pfad angeben. ./foo.binoder /usr/bin/foo.bin. Der Einfachheit halber existiert jedoch dieses Ding namens PATH. Es genügt also zu tippen, foo.binweil Sie /usr/binsich gerade auf Ihrem Weg befinden.

Und wenn Sie sich jemals gefragt , welche Datei über behoben ist foo.bin, whichist es , Ihnen zu sagen: /usr/bin/foo.bin.

Daher wird wahrscheinlich jedes andere UNIX-Tool, das sowohl ausführbare als auch nicht ausführbare Dateien als Argumente akzeptiert, keine Abfrage durchführen PATH.

user694971
quelle
1

Der Pfad wird von der Shell beim Ausführen von Programmen abgefragt, um das auszuführende Programm zu finden. Wenn es sich um einen Parameter handelt (z. B. um den Befehl whichoder statin Ihrem Beispiel), übergibt die Shell ihn nur an das gefundene Programm, und das Programm entscheidet, was damit geschehen soll.

Der whichBefehl ist in bash integriert. Er verwendet das Argument und durchsucht den Pfad der Shell, um herauszufinden, wie die Shell ihn ausführen würde. Die meisten anderen Programme (einschließlich der meisten anderen in bash integrierten Programme), wie statin Ihrem Beispiel, verwenden einfach den Pfad und versuchen, ihn im aktuellen Verzeichnis im Dateisystem zu finden.

Das Ausführen von Befehlen (und solche Dinge, bei whichdenen versucht wird, herauszufinden, welche Befehle ausgeführt werden sollen) sind die einzigen Dinge, die den PATH verwenden.

Peter Cooper Jr.
quelle