У меня есть SFTP-сервер, на который клиенты постоянно загружают большие файлы. Я хочу периодически копировать все полный (полностью загруженные) файлы на другой компьютер для обработки. Я не хочу копировать файл, в который идет активная запись. Есть ли способ добиться этого? В настоящее время я использую rsync, но готов переключиться на что-нибудь еще.
Чтобы проверить, открыт ли файл в настоящее время (если файл, который в настоящее время записывается, наверняка открыт каким-либо процессом), стандартным способом является использование lsof
:
if lsof /your/file > /dev/null; then echo "file currently open"; fi
Вы можете использовать этот фрагмент, чтобы отфильтровать результаты поиска только для неоткрытых файлов и использовать их для подачи rsync:
find . -type f -exec sh -c 'if ! lsof `readlink -f {}` > /dev/null; then echo `basename {}`; fi' \; | tr '\n' '\0' | rsync -avz --from0 --files-from=- ./ user@host:destination/
Некоторые примечания:
readlink -f
необходим для указания полного пути к файлу, lsof принимает только полный путьtr '\n' '\0'
подражать находке -print0
Одна из проблем здесь состоит в том, чтобы определить, записываются ли все еще файлы. Нет идеального способа сделать это. Я думаю, что лучшее, что вы можете сделать, - это просто проверить временную метку последнего изменения в файлах и скопировать только те файлы, которые не были изменены в течение нескольких минут.
rsync
сам по себе не может этого сделать, но вы можете комбинировать его с команда find:
cd /path/to/directory/with/files
find ./ -type f -mmin +5 -print0 | rsync --archive --verbose --from0 --files-from=- ./ yourotherserver:targetdir/
Чтобы разбить эту команду, она выполняет две вещи:
find ./ -type f -mmin +5 -print0
для определения всех файлов, которые не были изменены в течение как минимум 5 минут.rsync
используя --from0
и --files-from
параметры. Это сделает rsync
рассматривать только те файлы, которые find
определила.