Вопрос или проблема
Рассмотрим две команды, которые запланированы на выполнение одновременно (через Autosys, ровно в 8 утра).
Команда find
удаляет файлы старше 15 дней, но завершилась с ненулевым статусом с сообщением:
???find отсутствует /app/source/a.txt нет такого файла или каталога
Однако a.txt
всего один день. Почему команда find
проверяет недавний файл, который был в наличии во время ее выполнения, но переместился в другую папку в то же время?
find /app/source -type f -name -mtime +15 rm -f {} \;
mv /app/source/a.txt /app/backup/
Это то, что называется состоянием гонки. Единственный способ для find
узнать, что это новый файл, который не должен быть удален, — это посмотреть на файл. Поэтому find
сначала находит файл, а затем проверяет его дату.
В вашем случае, похоже, что ваша другая команда удалила файл после того, как find
увидела, что он присутствует в каталоге, но до того, как у нее было время проверить его возраст. Поэтому произошла ошибка.
Каталог в основном является списком имен файлов.
Когда вы запускаете find
и задаете тесты,
которые проверяют атрибуты/свойства файлов (а не только имя файла),
find
должен запрашивать файловую систему для получения атрибутов/свойств
каждого файла, указанного в каждом каталоге.
Таким образом, find
не имеет способа узнать, что a.txt
является недавним файлом,
кроме как вызвав stat("a.txt")
.
Как вы, вероятно, понимаете, ваша команда mv
переместила файл
между моментом, когда find
прочитал каталог, и моментом, когда она вызвала stat()
.
Ответ или решение
Почему команда find с -mtime не работает корректно для файлов, созданных в текущий день
Когда вы выполняете команду find
с использованием параметра -mtime
, вы сталкиваетесь с интересным поведением, касающимся определения времени модификации файлов. Рассмотрим случай, в котором две команды запускаются одновременно: одна команда предназначена для поиска и удаления файлов старше 15 дней, а другая — для перемещения файла a.txt
, который всего лишь на один день старше.
Распределение времени выполнения
В этом сценарии команда find
рассматривает содержимое директории и затем проверяет атрибуты файлов. Когда вы запускаете следующую команду:
find /app/source -type f -mtime +15 -exec rm -f {} \;
Команда find
сначала считывает список файлов в директории /app/source
, а затем для каждого найденного файла выполняет проверку по атрибутам, включая дату модификации. Это означает, что find
не знает ничего о состоянии файлов в момент, когда команда начинает выполняться, и делает отдельные запросы для проверки каждого файла.
Условия гонки (Race Condition)
Проблема, с которой вы столкнулись, является классическим примером условия гонки. В момент, когда команда find
начинает работать и уже считает, что файл a.txt
присутствует в директории, другая команда, выполняющая перемещение (mv /app/source/a.txt /app/backup/
), может исполниться и удалить файл из директории до того, как find
успевает проверить его атрибуты.
Это приводит к тому, что в момент, когда find
пытается выполнить проверку на наличие файла, он уже недоступен. Результатом будет ошибка "нет такого файла или директории", поскольку файл не существует в момент выполнения команды stat()
. В результате команда find
выдает ненулевой статус, что означает возникновение ошибки.
Решение проблемы
Для решения этой проблемы можно рассмотреть несколько подходов:
-
Отключение одновременного выполнения: Избегайте запуска команд, которые могут затрагивать одни и те же файлы одновременно. Например, синхронизируйте их выполнение с помощью блокировок или очередей.
-
Проверка состояния файлов перед выполнением: Можно использовать промежуточное состояние, в котором перед удалением файлов вы проверяете их существование заново, чтобы убедиться, что они не были перемещены или удалены.
-
Логирование и уведомления: Настройте логирование для того, чтобы отслеживать состояние файлов перед и после выполнения скриптов. Таким образом, можно будет отследить, что именно вызвало ошибку.
-
Использование безопасных инструментов: Рассмотрите возможность использования более совершенных инструментов для управления файлами, которые могут справляться с условиями гонки или предлагают более высокий уровень контроля.
Заключение
Понимание того, как командные строки взаимодействуют с файловой системой и особенностями работы команд, таких как find
, является ключевым моментом для избежания проблем в будущем. Условия гонки могут привести к неожиданным ошибкам, и важно учитывать их в своей стратегии автоматизации и администрирования. Следуя лучшим практикам и применяя предложенные рекомендации, вы сможете повысить надежность работы ваших скриптов и системы в целом.