Есть ли в 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...). В этом случае вы должны искать источник путем проб и ошибок.

Другие вопросы по тегам