¿Cómo borro el caché de Bash de rutas a los ejecutables?

257

Cuando ejecuto un programa sin especificar la ruta completa al ejecutable, y Bash debe buscar en los directorios $PATHpara encontrar el binario, parece que Bash recuerda la ruta en algún tipo de caché. Por ejemplo, instalé una compilación de Subversion desde el origen hasta /usr/local, luego escribí svnsync helpen el indicador Bash. Bash localizó el binario /usr/local/bin/svnsyncpara "svnsync" y lo ejecutó. Luego, cuando eliminé la instalación de Subversion /usr/localy volví a ejecutar svnsync help, Bash responde:

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

Pero, cuando comienzo una nueva instancia de Bash, se encuentra y se ejecuta /usr/bin/svnsync.

¿Cómo borro el caché de rutas a los ejecutables?

Daniel Trebbien
fuente
77
característica más estúpida de la historia
Romeno

Respuestas:

323

bashalmacena en caché la ruta completa a un comando. Puede verificar que el comando que está intentando ejecutar está en hash con el typecomando:

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

Para borrar todo el caché:

$ hash -r

O solo una entrada:

$ hash -d svnsync

Para información adicional, consultar help hashy man bash.

Tobu
fuente
15
@Daniel Vale la pena agregar que, en bash, puedes usar el comando "type command " para averiguar qué tipo de comando es; si tu comando está en hash, "type" te lo dirá. También es útil saber si algo es un shell incorporado o un alias.
lunchmeat317
44
Como FYI, para cambiar la RUTA en caché si se está ejecutando csh, el comando es rehash.
kurtm
El rehashcomando anterior también funciona para zsh.
Neil Traft
Para obtener una respuesta más completa, consulte unix.stackexchange.com/questions/86012/…
Ioannis Filippidis
44
En un comando, se puede invocar la repetición selectiva hash svnsync.
Ioannis Filippidis
25

Para borrar solo una entrada, necesita una bandera diferente:

hash -d svnsync

La -rbandera no toma un parámetro y siempre borrará todo el caché.
(Al menos en bash 3.2.39 en Debian Lenny)

Aryeh Leib Taurog
fuente
20

Hay soluciones no mencionadas aquí.

  1. Puede deshabilitar el hash con set +hoset +o hashall

    help set dice:

    -h: recuerda la ubicación de los comandos a medida que se buscan para su ejecución. Esto está habilitado por defecto.

    hashall: igual que -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. Puede comprobar que existe un comando que se encuentra en la tabla hash antes de intentar ejecutarlo con shopt -s checkhash

    help shopt dice:

    checkhash: si está configurado, bash verifica que exista un comando encontrado en la tabla hash antes de intentar ejecutarlo. Si ya no existe un comando hash, se realiza una búsqueda de ruta normal.

    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. Puede vincular NAME con PATH con hash -p PATH NAMEo 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. Magia: PATH="$PATH"realizahash -r

    De variables.c:

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

    Tratar:

    set -h
    hash -r
    date
    hash # prints 1 /bin/date
    PATH="$PATH"
    hash # prints hash: hash table empty
Evgeny Vereshchagin
fuente
1
Nunca he entendido por qué se proporciona todo el mecanismo adicional cuando PATH = $ PATH funciona bien. Si la RUTA cambia, entonces la caché de búsqueda RUTA debería ser invalidada. Tiene sentido.
jrw32982
El caso de uso no se maneja al invalidar el caché cuando cambia la RUTA cuando cambian las ubicaciones de los ejecutables. Esto puede ser común cuando está utilizando el shell para agregar o eliminar programas, solo para que guarde en caché el último lugar donde los encontró.
Adam
Jugar con la tabla hash de comandos es una forma maravillosa de confundir realmente a alguien que está tratando de depurar un script bash.
Erik Aronesty
4

Como el usuario johntex ha notado en un comentario a la respuesta del usuario Tobu , la acción práctica más simple en Bash es repetir solo su programa:

hash svnsync

Eso es todo.

Acumenus
fuente