Мне нужно развернуть автоматизированный процесс (через 1-минутный скрипт cron), который ищет файлы tar в определенной директории. Если файл tar найден, он не попадает в соответствующее место, а затем файл tar удаляется.
Файлы tar автоматически копируются на этот сервер через SSH с другого сервера. В некоторых случаях файлы tar очень большие, с большим количеством файлов.
Проблема, с которой я ожидаю столкнуться: если для копирования файла tar на сервер требуется> 1 минуты, а скрипт cron запускается раз в минуту, он увидит файл .tar.gz и попытается выполнить распакуйте его, хотя файл tar все еще находится в процессе записи.
Есть ли способ (с помощью команд bash) проверить, записывается ли файл в данный момент, или это только частичный файл и т. Д.?
Одна из альтернатив, о которой я думал, - это скопировать файл с другим расширением (например .tar.gz.part
), а затем переименовать .tar.gz
после завершения передачи. Но я решил, что постараюсь выяснить, есть ли просто способ определить, является ли файл первым в командной строке ... Есть какие-нибудь подсказки?
rsync
использует временное имя файла во время передачи (по умолчанию) и только после того, как файл полностью передан, переименовывает его в фактическое имя файла.Ответы:
Вы на правильном пути, переименование файла является атомарной операцией, поэтому выполнение переименования после загрузки является простым, элегантным и не подверженным ошибкам. Другой подход, который я могу придумать, состоит в том, чтобы использовать,
lsof | grep filename.tar.gz
чтобы проверить, доступен ли файл другому процессу.источник
lsof filename.tar.gz
более эффективно и точнее, чемlsof | grep filename.tar.gz
)Лучше всего использовать,
lsof
чтобы определить, был ли файл открыт каким-либо процессом:Вы не можете легко определить, находится ли он в процессе записи, но если он записывается, он ДОЛЖЕН быть открытым.
Изменить: давайте решим актуальную проблему здесь, а не пытаться реализовать предложенное решение!
Используйте rsync для передачи файла:
Таким образом, файл не будет скопирован поверх существующего, но будет скопирован во временный файл (
.big.tar.gz.XXXXXX
) до завершения передачи, а затем перемещен на место.источник
Немного стар, но большинство ответов совершенно не соответствует сути вопроса:
В общем, нет. Вам просто не хватает информации, чтобы определить это.
Потому что определение того, что файл закрыт, - это не то же самое, что определение, является ли файл целым . Например, файл будет «закрыт», если соединение потеряно во время передачи.
Только @ Алекс ответ получил это право. И даже он упал на использование
lsof
несколько.Чтобы определить, был ли файл полностью передан, требуется больше данных. Такие как:
Это прекрасный способ сообщить, что файл был полностью и успешно передан. Вы также можете перемещать файлы из одного каталога в другой, если вы остаетесь в одной файловой системе. Или отправитель должен отправить пустой
filename.done
файл, чтобы сообщить о завершении.Но все методы должны полагаться на отправителя, каким-то образом сигнализируя об успешном завершении передачи. Потому что только отправитель имеет эту информацию.
Некоторые форматы файлов (например, PDF-файлы) содержат данные, позволяющие определить, завершен ли файл. Но вы должны открыть и прочитать почти весь файл, чтобы узнать.
lsof
просто скажет вам, что файл больше не открыт - он не скажет вам, почему он больше не открыт. Он также не скажет вам, насколько большим должен быть файл.источник
Лучший способ сделать это - использовать incron («inotify cron system»). Это позволяет вам установить отслеживание inotify в каталоге, который затем уведомит вас о файловых операциях. В этом случае вы должны смотреть каталог для close_write. Это позволит вам запустить вашу команду, как только файл будет закрыт после записи.
источник
Похоже, что lsof может определить, в каком режиме открыт файл:
Видите, где написано 1w? Это означает, что номер дескриптора файла равен 1, а режим - w или write.
источник
FD
поле отображается3r
для меня , когда файл открыт для чтения.Использование
inotifywait
может достичь того, что вам нужно - у него есть возможность дождаться окончания записи файла перед выполнением команды.Следующее будет непрерывно наблюдать за папкой для новых файлов и выполнять команду в цикле, когда запись в файл будет завершена.
Дополнительные параметры конфигурации см. По адресу https://linux.die.net/man/1/inotifywatch.
источник