Wie lösche ich Bashs Cache mit Pfaden zu ausführbaren Dateien?

258

Wenn ich ein Programm ohne Angabe des vollständigen Pfads zur ausführbaren Datei ausführe und Bash die Verzeichnisse durchsuchen muss $PATH, um die Binärdatei zu finden, scheint sich Bash den Pfad in einer Art Cache zu merken. Zum Beispiel habe ich einen Build von Subversion von der Quelle bis installiert /usr/localund dann svnsync helpan der Bash-Eingabeaufforderung eingegeben . Bash hat die Binärdatei /usr/local/bin/svnsyncfür "svnsync" gefunden und ausgeführt. Wenn ich dann die Installation von Subversion in gelöscht /usr/localund erneut ausgeführt habe svnsync help, antwortet Bash:

bash: /usr/local/bin/svnsync: No such file or directory

Wenn ich jedoch eine neue Instanz von Bash starte, wird diese gefunden und ausgeführt /usr/bin/svnsync.

Wie lösche ich den Cache von Pfaden zu ausführbaren Dateien?

Daniel Trebbien
quelle
7
dümmste Funktion aller Zeiten
Romeno

Antworten:

325

bashZwischenspeichert den vollständigen Pfad zu einem Befehl. Sie können überprüfen, ob der Befehl, den Sie ausführen möchten, mit dem folgenden typeBefehl gehasht wurde :

$ type svnsync
svnsync is hashed (/usr/local/bin/svnsync)

So leeren Sie den gesamten Cache:

$ hash -r

Oder nur ein Eintrag:

$ hash -d svnsync

Weitere Informationen finden Sie unter help hashund man bash.

Tobu
quelle
15
@Daniel Es ist erwähnenswert, dass Sie in bash den Befehl "type command " verwenden können, um herauszufinden, um welche Art von Befehl es sich handelt. Wenn Ihr Befehl gehasht ist, gibt "type" dies an. Es ist auch nützlich zu erkennen, ob es sich um eine eingebaute Shell oder einen Alias ​​handelt.
lunchmeat317
4
Um den zwischengespeicherten PFAD zu ändern, wenn er ausgeführt wird csh, lautet der Befehl rehash.
Kurtm
Der obige rehashBefehl funktioniert auch für zsh.
Neil Traft
Eine vollständigere Antwort finden Sie unter unix.stackexchange.com/questions/86012/…
Ioannis Filippidis
4
In einem Befehl kann durch selektives Aufwärmen aufgerufen werden hash svnsync.
Ioannis Filippidis
25

Um nur einen Eintrag zu löschen, benötigen Sie eine andere Flagge:

hash -d svnsync

Das -rFlag nimmt keinen Parameter an und löscht immer den gesamten Cache.
(Zumindest in Bash 3.2.39 auf Debian Lenny)

Aryeh Leib Taurog
quelle
20

Es gibt Lösungen, die hier nicht erwähnt werden.

  1. Sie können Hashing mit set +hoder deaktivierenset +o hashall

    help set sagt:

    -h - Den Speicherort von Befehlen merken, wenn diese zur Ausführung gesucht werden. Dies ist standardmäßig aktiviert.

    hashall - Wie -h

    set -h # enable hashing
    shopt -u checkhash # disable command existence check
    hash -p /some/nonexisting/dir/date date # bind date with /some/nonexisting/dir/date
    date # bash: /some/nonexisting/dir/date: No such file or directory
    set +h
    date # normal date output
  2. Sie können überprüfen, ob ein Befehl in der Hash-Tabelle vorhanden ist, bevor Sie versuchen, ihn mit auszuführen shopt -s checkhash

    help shopt sagt:

    checkhash - Wenn gesetzt, prüft bash, ob ein Befehl in der Hash-Tabelle vorhanden ist, bevor versucht wird, ihn auszuführen. Wenn ein Hash-Befehl nicht mehr vorhanden ist, wird eine normale Pfadsuche ausgeführt.

    set -h # enable hashing
    shopt -u checkhash # disable command existence check
    hash -p /some/nonexisting/dir/date date # bind date with /some/nonexisting/dir/date
    hash -t date # prints /some/nonexisting/dir/date
    date # bash: /some/nonexisting/dir/date: No such file or directory
    shopt -s checkhash # enable command existence check
    date # normal date output
    hash -t date # prints /bin/date
  3. Sie können NAME mit PATH binden mit hash -p PATH NAMEoder BASH_CMDS[NAME]=PATH:

    shopt -u checkhash # disable command existence check
    hash -p /some/nonexisting/dir/date date
    date # bash: /some/nonexisting/dir/date: No such file or directory
    BASH_CMDS[date]=/bin/date
    date # normal date output
  4. Magie: PATH="$PATH"führthash -r

    Von variables.c:

    /* What to do just after the PATH variable has changed. */
    void
    sv_path (name)
        char *name;
    {
        /* hash -r */
        phash_flush ();
    }

    Versuchen:

    set -h
    hash -r
    date
    hash # prints 1 /bin/date
    PATH="$PATH"
    hash # prints hash: hash table empty
Evgeny Vereshchagin
quelle
1
Ich habe nie verstanden, warum der gesamte zusätzliche Mechanismus mitgeliefert wird, wenn PATH = $ PATH einwandfrei funktioniert. Wenn sich der PATH ändert, sollte der PATH-Lookup-Cache ungültig werden. Macht Sinn.
jrw32982
Der Anwendungsfall, bei dem der Cache nicht ungültig gemacht wird, wenn sich der Pfad ändert, liegt vor, wenn sich die Positionen der ausführbaren Dateien ändern. Dies kann häufig der Fall sein, wenn Sie die Shell zum Hinzufügen oder Entfernen von Programmen verwenden, damit diese nur an der letzten Stelle zwischengespeichert werden, an der sie gefunden wurden.
Adam
Das Spiel mit der Command-Hash-Tabelle ist eine wunderbare Möglichkeit, jemanden zu verwirren, der versucht, ein Bash-Skript zu debuggen.
Erik Aronesty
4

Wie Benutzer johntex in einem Kommentar zu der Antwort von Benutzer Tobu angemerkt hat , besteht die einfachste praktische Aktion in Bash darin, nur Ihr Programm erneut aufzubereiten:

hash svnsync

Das ist alles.

Acumenus
quelle