Как «cp» обрабатывает открытые файлы?

15

У меня есть два отдельных каталога. Пользователь загружает файл в первый. Theres cronjob работает в фоновом режиме, который копирует файлы каждые 5 минут во второй каталог.

Что произойдет, если пользователь не завершил загрузку и cronjob скопирует файлы? Обратите внимание, что эти два каталога принадлежат разным пользователям, cronjob выполняется как root.

заложенный
источник
пожалуйста, прочитайте этот пост, чтобы увидеть, что происходит в таком случае: unix.stackexchange.com/questions/49299/…
Серж
Спасибо, хороший пост, который вы написали. Но мой вопрос был больше связан с cp, а не с обработкой linux-файлов в целом. Хотя, возможно, cp проверяет, открыт ли файл, и ждет его закрытия или что-то в этом роде.
Stuffy
Нет cp, не будет ждать, пока файл полностью загружен. Поскольку мы ожидаем, что скорость передачи по сети ниже, чем просто копирование файла из одного места в другое на том же хосте, то в определенный момент cpон достигнет текущего конца файла и прекратит копирование. Решение вашей проблемы может быть простым: сначала пользователь загружает файл с каким-то специально искаженным именем файла (например, с префиксом .(символ точки). Когда передача завершена, пользователь переименовывает его в исходное имя. Затем задание cron выглядит только для файлов, которые не начинаются с ..
Серж

Ответы:

17

cpне знает об открытых файлах. Таким образом, если первый пользователь загрузит большой файл и cronjob (или любой другой процесс) начнет копировать этот файл, он будет копировать только столько, сколько уже было написано. Вы можете думать об этом следующим образом - cpкопировать то, что в данный момент находится на диске, независимо от того, завершен ли файл. В противном случае, вы не можете скопировать файлы журнала, например.

Кшиштоф Адамски
источник
Спасибо, вот что я хотел знать! Есть ли простой способ избежать этого? Я проверил справочную страницу cp, но ничего не нашел.
Stuffy
Для чего именно? Чтобы скопировать все файлы, кроме открытых? Я не думаю, что есть какой-то простой способ сделать это (кроме написания вашего собственного скрипта, который использует fuser+ cp. Такая копия действительно была бы очень ненадежной. Она не будет копировать любой файл, открытый, например, в текстовом редакторе.
Krzysztof Адамски
@ Stuffy, может быть, в вашем cronjob вы могли бы перечислить открытые файлы с lsof? Результат этого должен быть простым в обработке. Вы можете отфильтровать открываемые файлы (скажем, экземпляром cp) для записи.
Войтек Жепала
@ WojtekRzepala, я посмотрю на это, спасибо. Может быть, я напишу небольшой сценарий, который выполняется cronjob
Stuffy
@Stuffy: Имейте в виду, что он может быть ненадежным, если он не запускается пользователем root (с той же проблемой, fuserконечно), поскольку этот инструмент может отображать не все файлы.
Кшиштоф Адамски
7

cpне знает, какие другие программы могут иметь открытые файлы. В этом нет магии cp. Дизайн unix целенаправленно избегает наложения каких-либо блокировок на файлы, если нет веской причины (убедительный смысл в том, что ядру это нужно). В этом разделе см. « Применяет ли блокировка для файла перенаправление вывода в файл?

Такие ситуации, когда файл создается производителем и после его завершения потребителем является распространенным явлением. Обычный способ справиться с этим - заставить производителя написать временный файл, который потребитель не будет искать, а затем, как только производитель закончит, переместите файл в место, где его найдет потребитель. Перемещение файла (в той же файловой системе) является атомарной операцией: в какой-то момент, для потребителя, файл изменяется от отсутствия там к тому, чтобы быть там.

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

Жиль "ТАК - прекрати быть злым"
источник
6

Похоже, что вы хотите сделать работу Dir Sync.

Потому что опция -u, --updatecp

копировать только в том случае, если файл SOURCE новее файла назначения или отсутствует файл назначения

Таким образом, вы можете добавить cronjob, например, cp -auv SOURCEDIR/* DESTDIRкоторый будет копировать те файлы, время модификации которых изменилось. Это значит, DESTDIRчто в конечном итоге вы получите полную копию, когда загрузка будет завершена.

rsyncможет сделать ту же работу. например, rsync -av SOURCEDIR/ DESTDIR.

Хотя опция -a применяется, некоторые указанные атрибуты (например, владение) могут быть сохранены только суперпользователем.

См man cp, man rsyncдля деталей.

Edw4rd
источник
Просто остерегайтесь полагаться на последние записи в папке назначения - они могут быть не полными файлами.
dubiousjim