Dlaczego „typ, który” mówi, że „hashed”?

31

W przypadku wbudowanych powłok (np. Siebie type):

$ type type
type is a shell builtin

$ which type
<Doesn't return anything since it's a shell builtin, silently exits>

W przypadku poleceń (normalnie) (np. python):

$ type python
python is /usr/bin/python

$ which python
/usr/bin/python

W przypadku which(który jest poleceniem znajdującym się w /usr/bin/which)

$ type which
which is hashed (/usr/bin/which)
$ which which
/usr/bin/which

Dlaczego to type whichmówi which is hashed? Jakie jest znaczenie whichbycia mieszanym i co to właściwie znaczy?

Aditya
źródło

Odpowiedzi:

40

Prawdopodobnie masz długi zestaw PATH i aby znaleźć plik wykonywalny, powłoka musi przeszukać ścieżkę. Aby uniknąć tego czasochłonnego procesu za każdym razem, gdy chcesz uruchomić program, powłoka może przechowywać listę programów, które już znalazła. Ta lista nazywa się „skrótem”. Kiedy powłoka mówi, że whichjest zaszyfrowana, oznacza to, że już przeprowadziła wyszukiwanie ŚCIEŻKI, znalazła whichi zapisała swoją lokalizację w haszowaniu.

man bash wyjaśnia to w następujący sposób:

Bash używa tabeli skrótów do zapamiętywania pełnych ścieżek plików wykonywalnych (patrz skrót w POLECENIA WBUDOWANE POWŁOKI poniżej). Pełne wyszukiwanie katalogów w zmiennej PATH jest wykonywane tylko wtedy, gdy polecenia nie znaleziono w tabeli skrótów.

Podczas gdy skrót zwykle przyspiesza operacje powłoki, jest jeden przypadek, w którym powoduje problemy. Jeśli zaktualizujesz system, w wyniku czego niektóre pliki wykonywalne zostaną przeniesione do nowej lokalizacji, powłoka może się pomylić. Rozwiązaniem jest uruchomienie, hash -rktóre powoduje, że powłoka zapomina o wszystkich zakodowanych lokalizacjach i przeszukuje ŚCIEŻKĘ od zera.

Dlaczego w haszu brakuje niektórych plików wykonywalnych?

Plik wykonywalny nie jest umieszczany w haszu, dopóki nie zostanie wykonany przynajmniej raz. Przestrzegać:

$ type python
python is /usr/bin/python
$ python --version
Python 2.7.3
$ type python
python is hashed (/usr/bin/python)

python jest mieszany dopiero po jego wykonaniu.

Jak sprawdzić, co jest w haszu bash

Zawartość skrótu jest dostępna w bashtablicy BASH_CMDS. Za pomocą polecenia możesz zobaczyć, co jest w środku declare -p BASH_CMDS. Po otwarciu nowej powłoki lub podpowłoki skrót jest pusty. Polecenia są dodawane jeden po drugim, gdy są używane. Z nowo otwartej powłoki obserwuj:

$ declare -p BASH_CMDS
declare -A BASH_CMDS='()'
$ which which
/bin/which
$ declare -p BASH_CMDS
declare -A BASH_CMDS='([which]="/bin/which" )'
$ python --version
Python 2.7.3
$ declare -p BASH_CMDS
declare -A BASH_CMDS='([which]="/bin/which" [python]="/usr/bin/python" )'
John1024
źródło
+1, całkiem dobre wytłumaczenie. Ale dlaczego za, whicha nie za python?
jobin
@Jobin Zobacz zaktualizowaną odpowiedź.
John1024
2
Wygląda na to, że skrót utrzymuje się tylko do czasu, gdy nie wyjdziemy z powłoki. Po ponownym uruchomieniu terminala nie jest powiedziane, że polecenie zostało zaszyfrowane.
Aditya
1
@Aditya Tak. Do odpowiedzi dodałem sekcję na ten temat.
John1024
hash -lbyłoby łatwiejsze w użyciu niżdeclare -p BASH_CMDS
phuclv