Как очистить кэш путей Bash к исполняемым файлам?

257

Когда я выполняю программу без указания полного пути к исполняемому файлу, и Bash должен искать в каталогах, $PATHчтобы найти двоичный файл, кажется, что Bash запоминает путь в каком-то кеше. Например, я установил сборку Subversion из исходного кода в /usr/local, а затем набрал svnsync helpв приглашении Bash. Bash /usr/local/bin/svnsyncобнаружил двоичный файл для svnsync и выполнил его. Затем, когда я удалил установку Subversion /usr/localи снова запустил ее svnsync help, Bash отвечает:

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

Но когда я запускаю новый экземпляр Bash, он находит и выполняет /usr/bin/svnsync.

Как очистить кэш путей к исполняемым файлам?

Даниэль Треббиен
источник
7
самая глупая особенность в истории
Ромено

Ответы:

323

bashкэширует полный путь к команде. Вы можете проверить, что команда, которую вы пытаетесь выполнить, хешируется с помощью typeкоманды:

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

Чтобы очистить весь кэш:

$ hash -r

Или только одна запись:

$ hash -d svnsync

За дополнительной информацией обращайтесь help hashи man bash.

Tobu
источник
15
@Daniel Стоит добавить , что в Баш, вы можете использовать «тип команды команду » , чтобы выяснить , какой тип команды это - если ваша команда хешируется, «тип» скажу. Также полезно узнать, является ли что-то встроенным в оболочку или псевдоним.
lunchmeat317
4
В качестве FYI, чтобы изменить кэшированный PATH, если выполняется csh, команда rehash.
Куртм
Вышеприведенная rehashкоманда также работает для zsh.
Нил Трафт
Для более полного ответа см. Unix.stackexchange.com/questions/86012/…
Иоаннис Филиппидис
4
В одной команде выборочная перефразировка может быть вызвана hash svnsync.
Иоаннис Филиппидис
25

Чтобы очистить только одну запись, вам нужен другой флаг:

hash -d svnsync

-rФлаг не принимает параметр и всегда будет удалять весь кэш.
(По крайней мере, в bash 3.2.39 на Debian Lenny)

Арье Лейб Таурог
источник
20

Есть решения, не упомянутые здесь.

  1. Вы можете отключить хеширование с помощью set +hилиset +o hashall

    help set говорит:

    -h - Запомните расположение команд при их поиске для выполнения. Это включено по умолчанию.

    hashall - такой же, как -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. Вы можете проверить, что команда, найденная в хеш-таблице, существует, прежде чем пытаться выполнить ее с shopt -s checkhash

    help shopt говорит:

    checkhash - если установлено, bash проверяет, что команда, найденная в хеш-таблице, существует, прежде чем пытаться ее выполнить. Если хешированная команда больше не существует, выполняется обычный поиск пути.

    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. Вы можете связать NAME с PATH с помощью hash -p PATH NAMEили 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. Магия: PATH="$PATH"выполняетhash -r

    От variables.c:

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

    Пытаться:

    set -h
    hash -r
    date
    hash # prints 1 /bin/date
    PATH="$PATH"
    hash # prints hash: hash table empty
Евгений Верещагин
источник
1
Я никогда не понимал, почему весь дополнительный механизм предоставляется, когда PATH = $ PATH работает просто отлично. Если PATH изменяется, то кеш поиска PATH должен быть аннулирован. Имеет смысл.
jrw32982
Вариант использования, который не обрабатывается путем аннулирования кэша при изменении PATH, - это когда меняются местоположения исполняемых файлов. Это может быть распространено, когда вы используете оболочку для добавления или удаления программ, только для того, чтобы она кешировала последнее место, где она их нашла.
Адам
Использование хеш-таблицы команд - замечательный способ действительно запутать кого-то, кто пытается отладить скрипт bash.
Эрик Аронесты
4

Как отметил пользователь johntex в комментарии к ответу пользователя Tobu , самое простое практическое действие в Bash - перефразировать только вашу программу:

hash svnsync

Вот и все.

Акаменус
источник