Отключить кэш bash исполняемых файлов в пути

12

Обратите внимание, что это не дубликат. Я прошу отключить кеш, а не очищать его. Если у вас есть кэш для очистки, то он, очевидно, не отключен.

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

~ dc$ export PATH=$HOME/bin:$PATH
~ dc$ cat bin/which
#!/bin/bash
echo "my which"
~ dc$ which
my which
~ dc$ rm bin/which
~ dc$ which which
-bash: /Users/dc/bin/which: No such file or directory

В другой оболочке ...

~ dc$ which which
/usr/bin/which

Я уверен, что это кэширование имело смысл еще в старые добрые времена, когда диски были медленными, а память была дорогой и ограниченной, и поэтому вы не могли много кешировать - кэширование пути дешевле, чем кэширование всех дисковых блоков, необходимых для поиска команды , Но в наши дни это не дает заметной выгоды и вызывает больше проблем, чем решает. Это ошибка, граничащая с ошибкой.

И я даже не могу найти способ отключить его. Есть указатели?

DrHyde
источник
1
Преимущества заметны даже в обычном случае настольного компьютера, если у вас не так много оперативной памяти, которая /usr/binполностью остается в кеше.
Жиль "ТАК - перестань быть злым"
1
@ drhyde, прости. Я отметил этот вопрос как дубликат. Используйте set +hдля отключения хеширования.
Евгений Верещагин
В Nixos он отключил хэш в своем bash. Я думаю, что на то есть веская причина из-за способа работы Nixos. Однако я не уверен, действительно ли это обязательно для Nixos. Я только говорю, что хэш в bash может вызвать проблемы в определенных ситуациях.
typelogic

Ответы:

12

Вы можете просто очистить хешированные исполняемые файлы до того, как появится приглашение:

PROMPT_COMMAND='hash -r'

От help hash:

hash: hash [-lr] [-p pathname] [-dt] [name ...]
Remember or display program locations.

Determine and remember the full pathname of each command NAME.  If
no arguments are given, information about remembered commands is displayed.

Options:
  -d                forget the remembered location of each NAME
  -l                display in a format that may be reused as input
  -p pathname       use PATHNAME is the full pathname of NAME
  -r                forget all remembered locations
  -t                print the remembered location of each NAME, preceding
            each location with the corresponding NAME if multiple
            NAMEs are given
Arguments:
  NAME              Each NAME is searched for in $PATH and added to the list
            of remembered commands.

Exit Status:
Returns success unless NAME is not found or an invalid option is given.
Крис Даун
источник
1
см. мой ответ оset +h
Евгений Верещагин
1
@EvgenyVereshchagin set +hне идеален, так как многие утилиты (например, установки ruby ​​gem) вызывают hash, генерируя потоки -bash: hash: hashing disabledпредупреждений.
Дэвид Моулз
Я также вижу такие же предупреждающие сообщения при активации python virtualenv. Но я думаю, это безвредно.
typelogic
8

Вы можете заставить bash выполнить поиск нового пути, если команды в хеш-таблице больше не существует.

shopt -s checkhash

Из справочной страницы Bash:

checkhash

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

Пример:

[blabla]$ PATH=$HOME/bin:$PATH
[blabla]$ hash -r
[blabla]$ cat bin/which
#!/bin/bash
echo "my which"
[blabla]$
[blabla]$ shopt -s checkhash
[blabla]$ which
my which
[blabla]$ mv bin/which bin/dis.which
[blabla]$ which which
/usr/bin/which
user70408
источник