Есть ли в Bash кеш исполняемых файлов?
Я просто писал программу на C++ на моем компьютере с Ubuntu 14.10. Поскольку это клиент-серверная программа, у меня открыто три эмулятора терминала: один для написания кода и компиляции, один для тестирования клиента и последний для тестирования сервера. Через некоторое время я подумал, что в моем коде есть ошибка. Я потерял более часа, выслеживая его, и оказалось, что выход из каталога и повторный вход в него решили всю проблему. Чтобы быть точным, это были команды, которые я выполнил:
some_directory$ ./client
some_directory$ cd ..
$ cd some_directory
some_directory$ ./client
Ничего не изменив и не перекомпилировав, оба прогона дали разные результаты. Единственное, о чем я могу думать, это какой-то кэш, в котором хранятся старые версии файлов, но я никогда не слышал о такой возможности. Есть ли объяснение и как его решить (заставить его обновляться автоматически, не выходя из каталога)?
2 ответа
Я не думаю, что bash делает что-то необычное (он кеширует пути к исполняемым файлам, указанным без путей, но здесь это неприменимо, так как вы указываете путь)
Похоже, каталог, в котором вы были, был перемещен или смонтирован. В случае создания программного обеспечения, перемещение каталога более вероятно.
Случай перемещения каталога
Пример воссоздания поведения перемещения каталога в терминале 1
cd /tmp
mkdir dir1
cd dir1
touch exampleFile
Затем в терминале 2:
cd /tmp
mv dir1 dir2
mkdir dir1
cd dir1
Обе оболочки отображаются как находящиеся в каталоге с именем 'dir1', но список будет отображать различное содержимое. Если терминал2 создает файл с именем "exampleFile", обе оболочки будут показывать "exampleFile" в "dir1", но это разные файлы. Это потому, что оболочка в терминале 1 фактически находится в dir2, она просто не знает об этом. Оболочка в терминале 1 может добраться до реального dir1 через cd:
cd .
Это выглядит странно, но заново разрешает путь.
Над креплением
Это происходит, когда оболочка (или любая программа) находится в каталоге, а затем над ним монтируется файловая система. Например, в терминале 1:
mkdir /tmp/dir1
cd /tmp/dir1
терминал 2:
mount /dev/whateverdev /tmp/dir1
cd /tmp/dir1
Терминал 1 видит файлы из исходной файловой системы в этом каталоге. Терминал 2 видит файлы из /dev/whatdev.
Как избежать
В случае перемонтирования, это в основном просто осведомленность о том, что вы делаете или как настроена ваша машина (например, если автомонтирование работает, когда подключен USB-накопитель).
В случае перемещения каталогов это зависит немного больше от системы сборки. Если есть правило, которое создает резервную копию старого выходного каталога путем его перемещения, а затем создает новый каталог для новой сборки, вы будете сталкиваться с этой ситуацией довольно часто. Проверьте свои правила сборки для обмана.
Конечно, это также мог быть случайный случайный несчастный случай (аналогичный тому, что был показан в первом примере выше). В этом случае, понимание того, что это может произойти, поможет вам.
В общем hash
а такжеsync
hash
- встроенная командаbash
Для ускорения операции при выполнении команды оболочка bash сохраняет свойпуть в хеш-таблице. каждый shell
экземпляр имеет свойhash table
, Для получения дополнительной информации прочитайте эту выдержку из man bash
:
Если имя не является ни функцией оболочки, нивстроеннойфункцией и не содержит косых черт, bash ищет каждый элемент
PATH
для каталога, содержащего исполняемый файл с этим именем.
Bash используетхеш-таблицу, чтобы запомнить полные имена исполняемых файлов (см.hash
подОБОЛОЧКАМИ ПОСТРОЕННЫХ ниже Полный поиск по каталогам вPATH
выполняется только в том случае, если команда не найдена в хэш-таблице.
Вы можете заменить запись в списке (например, команда client
) с hash client
; Вы можете удалить эту запись из списка с помощью hash -d client
; вы можете сбросить список полностью с hash -r
,
Sync
- синхронизировать данные на диске с памятью
sync
Команда гарантирует, что все в памяти записывается на диск.
Для ускорения работы часто Linux может хранить некоторые данные в буферах файловой системы ядра, т.е. данные, которые были запланированы для записи с помощью системных вызовов низкоуровневого ввода-вывода [1].
С другой стороны, "жесткие диски могут по умолчанию использовать свой собственный энергозависимый кэш записи для буферизации записи, что значительно повышает производительность, в то же время создавая потенциал для потерянных записей" [2]
sync
записывает любые данные, буферизованные в памяти, на диск. Это может включать (но не ограничиваясь этим) измененные суперблоки, модифицированные inode и отложенные операции чтения и записи. Это должно быть реализовано ядром;sync
Программа выполняет только системный вызов sync. Ядро хранит данные в памяти, чтобы избежать (относительно медленных) чтения и записи на диск. Это улучшает производительность, но...
[если вы заинтересованы, продолжайте читать здесь или с info coreutils sync
].
Специфично для вашей проблемы
Если ваша проблема зависит от одного из вышеперечисленных аспектов, вы можете попытаться написать в одной строке более одной команды и после быстрого вызова их с помощью клавиши со стрелкой вверх, например:
hash -d ./client; ./client
,sync ; ./client
,hash -d ./client ; sync ; ./client
(cd .. ; cd - ; ./client )
Ваше собственное решение. Здесь вы выполняете клиент в подоболочке, которая наследует все, что вы сделали в своей оболочке (как переменные...), но не возвращает изменений в текущую оболочку.
Без полного понимания операций, выполняемых на этапах компиляции и операции набора между клиентом и сервером, может быть трудно найти причину (это может быть даже символическая ссылка или высокая задержка в файловой системе NFS...). В этом случае вы должны искать источник путем проб и ошибок.