Jak Unix wyszukuje pliki wykonywalne?

47

Kiedy plik jest wykonywany, w jaki sposób Unix go szuka? Jeśli w PATH znajduje się wiele plików wykonywalnych o tej samej nazwie, który z nich jest preferowany? Czy bieżący katalog jest uwzględniany podczas wyszukiwania pliku?

Załóżmy, że executable.shw bieżącym katalogu znajduje się plik o nazwie . Czy to zadziałałoby, gdyby zostało wykonane $ executedi .nie jest częścią PATH?

Leonid
źródło
przywołanie which <executable>polecenia będzie przydatne w tym wątku.
Księgowy م

Odpowiedzi:

45

$ PATH jest przeszukiwany od początku do końca, uruchamiany jest pierwszy zgodny plik wykonywalny. Tak więc katalogi na początku $ PATH mają pierwszeństwo przed katalogami, które pojawią się później. Pliki wykonywalne w bieżącym katalogu (.) Są wykonywane tylko wtedy, gdy. jest w $ PATH (co zwykle nie jest ). Nie ma domyślnego włączenia bieżącego katalogu do ścieżki wyszukiwania.

coneslayer
źródło
To dziwne, że mój $ PATH nie zawiera ., ale wygląda na to, że najpierw przeszukałby bieżący katalog, a potem katalogi kontrolne zdefiniowane w $ PATH.
Eric Wang
19

W przypadku plików w bieżącym katalogu należy je poprzedzić ./, aby komenda stała się ./executable.sh. Nigdy nie powinieneś mieć .w swojej ŚCIEŻCE, ponieważ stwarza to zagrożenie bezpieczeństwa, między innymi problemy.

Katalogi, które są pierwsze w ŚCIEŻCE i wyszukiwane jako pierwsze.

Ogólny porządek na poszukiwania jest podobny do tego, jeśli dobrze pamiętam:

  • aliasy

  • eksportowane funkcje

  • wbudowane polecenia powłoki

  • skrypty i pliki binarne w ŚCIEŻCE

John T.
źródło
7
Dodałbym skrót - pamiętaj, że bash (i może inne powłoki) przechowują skrót ostatnio używanych poleceń, aby ułatwić ich znalezienie. Czasami musisz wyczyścić pamięć podręczną (używając hash -r), jeśli zmienisz ŚCIEŻKĘ lub lokalizację programu.
Rich Homolka
3
+1 za kolejność wyszukiwania. Byłoby miło, gdybyś pamiętał źródło informacji :)
twan163,
8

Chociaż niektórzy inni dobrze na to odpowiedzieli, chciałbym dodać kilka przemyśleń:

1) PATH jest sprawdzane tylko wtedy, gdy wywoływany plik wykonywalny nie zawiera elementów ścieżki. somecommand będzie wyglądał w $ PATH, ./somecommandlub /usr/bin/somecommand, czy ../../bin/somecommandtylko zasady katalogów używają, nie PATH

Jeśli w PATH znajduje się wiele plików wykonywalnych o tej samej nazwie, który z nich jest preferowany?

Zatrzymuje się przy pierwszym znalezionym, odczytując $ PATH od lewej do prawej.

Czy bieżący katalog jest uwzględniany podczas wyszukiwania pliku?

Jeśli bieżący katalog znajduje się w zmiennej PATH, wówczas jest przeszukiwany. Pamiętaj, że pusty katalog w zmiennej PATH zawiera katalog bieżący. np. PATH =: / usr / bin (wiodący pusty) PATH = / usr / bin: (końcowy pusty) i PATH = / usr / bin :: / bin (środkowy pusty) wszystko efektywnie obejmie bieżący katalog roboczy.

Załóżmy, że w bieżącym katalogu znajduje się plik o nazwie executable.sh. Czy to zadziałałoby, gdyby zostało wykonane $ wykonane i. nie jest częścią ŚCIEŻKI?

Nie znalazłby go, wyszukując ŚCIEŻKĘ. Jeśli bieżący katalog nie znajduje się w ŚCIEŻCE, nie znajdzie go podczas wyszukiwania ŚCIEŻKI.

To powiedziawszy (i przepraszam za zamieszanie), jeśli istnieje alias lub funkcja, która uruchamia polecenie, zostanie uruchomione. Lub jeśli twoja powłoka ma pamięć podręczną lokalizacji, a plik wykonywalny znajduje się w pamięci podręcznej, może ją znaleźć. Tak więc nigdy nie znajdzie go w ŚCIEŻCE, ale może być uruchamiany w inny sposób.

Rich Homolka
źródło
Dzięki za cachenotatkę, prawie doprowadza mnie do szału, że stary plik wykonywalny /usr/bin/jest nadal wywoływany, a nie nowy w /usr/local/bin, ale jest po lewej stronie, $PATHaż wylogowałem się i zalogowałem ponownie.
Księgowy م
1
@ theaccountant w bash można zrobić 'hash -r', aby wyczyścić pamięć podręczną powłoki
Rich Homolka
4

Aby zobaczyć, jaka jest obecnie twoja ścieżka, po prostu wpisz echo $PATHlub printenv PATH.

Wtedy poznasz kolejność wyszukiwania. Jeśli masz wiele plików o tej samej nazwie, po prostu uruchom który ____, aby zobaczyć.

Dawny.

system #> który grep

/ usr / bin / grep

fajnym sposobem na znalezienie plików, które działają jak twój cel, jest użycie apropos:

apropos grep

bzgrep (1) - wyszukaj ewentualnie skompresowane pliki bzip2 dla wyrażenia regularnego

egrep (1) - drukuje linie pasujące do wzoru

fgrep (1) - drukuje linie pasujące do wzoru

grep (1) - drukuje linie pasujące do wzoru

i tak dalej...

Mbb
źródło
2
O tak - zapomniałem funkcji whereis, aby znaleźć WSZYSTKIE wystąpienia pliku:> whereis grep
mbb
grep: / bin / grep / usr / bin / grep /usr/share/man/man1/grep.1.gz
mbb
whereisużywa zakodowanej listy lokalizacji, a nie $PATH.
grawity
@grawity Czy możesz to rozwinąć?
WinEunuuchs2Unix
-2

@ coneslayer - Domyślna kolejność wyszukiwania plików wykonywalnych to bieżąca ścieżka, wbudowane polecenia, a następnie $ PATH. Więc jeśli funkcja o nazwie wykonywalnej już istnieje w pwd, to jest wykonywana. Jeśli nie to pierwszeństwo szuka wbudowanych poleceń powłoki, a następnie $ PATH

proc
źródło
Jeśli mówiłeś o skorupie Thompsona, skorupie Mashey lub innej skamieniałej pozostałości sprzed 40 lat, możesz mieć rację. Ale żadna bieżąca, uniwersalna powłoka uniksowa nie przeszukuje automatycznie bieżącego katalogu.
Scott,
@Scott Więc domyślna ścieżka wyszukiwania dla polecenia jest najpierw wbudowana, a następnie $ PATH i przeszukuje CWD tylko jeśli podam ./? Czy mam rację?
proc
Cóż, aliasy, funkcje i wbudowane funkcje. Następnie, jeśli podasz ścieżkę za pomocą polecenia (w tym ./), przeszukuje tylko ten katalog; w przeciwnym razie wyszukuje $PATH.
Scott,