Como limpo o cache de caminhos do Bash para executáveis?

256

Quando executo um programa sem especificar o caminho completo para o executável, e o Bash deve pesquisar os diretórios $PATHpara encontrar o binário, parece que o Bash se lembra do caminho em algum tipo de cache. Por exemplo, instalei uma compilação do Subversion da fonte para /usr/locale digitei svnsync helpno prompt do Bash. Bash localizou o binário /usr/local/bin/svnsyncpara "svnsync" e o executou. Então, quando eu excluí a instalação do Subversion /usr/locale a executei novamente svnsync help, o Bash respondeu:

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

Mas, quando inicio uma nova instância do Bash, ele localiza e executa /usr/bin/svnsync.

Como limpo o cache de caminhos para os executáveis?

Daniel Trebbien
fonte
7
recurso mais estúpido de todos os tempos
Romeno

Respostas:

322

basharmazena em cache o caminho completo para um comando. Você pode verificar se o comando que você está tentando executar possui um hash com o typecomando:

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

Para limpar o cache inteiro:

$ hash -r

Ou apenas uma entrada:

$ hash -d svnsync

Para informações adicionais, consulte help hashe man bash.

Tobu
fonte
15
@ Daniel Vale a pena acrescentar que, no bash, você pode usar o comando "type command " para descobrir que tipo de comando é - se o seu comando estiver com hash, "type" dirá a você. Também é útil dizer se algo é um shell embutido ou um pseudônimo.
Lunchmeat317
4
Como FYI, para alterar o PATH em cache, se estiver executando csh, o comando é rehash.
Kurtm # 12/13
O rehashcomando acima também funciona para zsh.
Neil Traft
Para obter uma resposta mais completa, consulte unix.stackexchange.com/questions/86012/…
Ioannis Filippidis
4
Em um comando, o rehashing seletivo pode ser chamado por hash svnsync.
Ioannis Filippidis
25

Para limpar apenas uma entrada, você precisa de um sinalizador diferente:

hash -d svnsync

O -rsinalizador não aceita um parâmetro e sempre exclui o cache inteiro.
(Pelo menos no bash 3.2.39 no Debian Lenny)

Aryeh Leib Taurog
fonte
20

Existem soluções não mencionadas aqui.

  1. Você pode desativar o hash com set +houset +o hashall

    help set diz:

    -h - Lembre-se da localização dos comandos conforme eles são procurados para execução. Isso é ativado por padrão.

    hashall - o mesmo 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. Você pode verificar se existe um comando encontrado na tabela de hash antes de tentar executá-lo com shopt -s checkhash

    help shopt diz:

    checkhash - Se definido, o bash verifica se existe um comando encontrado na tabela de hash antes de tentar executá-lo. Se um comando hash não existir mais, uma pesquisa de caminho normal será executada.

    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. Você pode vincular NAME a PATH com hash -p PATH NAMEou 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"executahash -r

    De variables.c:

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

    Experimentar:

    set -h
    hash -r
    date
    hash # prints 1 /bin/date
    PATH="$PATH"
    hash # prints hash: hash table empty
Evgeny Vereshchagin
fonte
1
Eu nunca entendi por que todo o mecanismo extra é fornecido quando PATH = $ PATH funciona muito bem. Se o PATH for alterado, o cache de pesquisa do PATH deverá ser invalidado. Faz sentido.
Jrw32982
O caso de uso não tratado ao invalidar o cache quando o PATH é alterado é quando os locais dos executáveis ​​são alterados. Isso pode ser comum quando você está usando o shell para adicionar ou remover programas, apenas para que ele seja armazenado em cache no último local em que os encontrou.
Adam
Mexer com a tabela de hash do comando é uma maneira maravilhosa de realmente confundir alguém que está tentando depurar um script do bash.
Erik Aronesty
4

Como o usuário johntex observou em um comentário à resposta do usuário Tobu , a ação prática mais simples no Bash é refazer a tarefa apenas do seu programa:

hash svnsync

Isso é tudo.

Acumenus
fonte