Почему "rsync --delete-before" удаляет файлы из цели, которые все еще существуют в источнике?

У меня есть CentOS 7.1 Linux окно с rsync 3.1.1. Там есть файлы, которые я хочу перенести на машину FreeNAS 9.10. Для этого я установил демон rsync на freeNAS, и передача файлов работает нормально. Но когда файлы удаляются в источнике, я хочу, чтобы они также были удалены из цели. Поэтому я добавил --delete-before к команде rsync, которую я запускаю на Linux. Почему "до", а не нормальное удаление? Потому что я использую parallel чтобы ускорить синхронизацию, запустив несколько rsyncs одновременно. Параллелизированный rsync не может быть объединен с удалением, потому что каждый экземпляр rsync видит только небольшую часть набора файлов и будет удалять большое количество файлов, если он будет объединен с командой удаления, возможно, даже удаляя файлы, которые будут иметь другие потоки просто положи туда. Поэтому вместо этого я сначала запускаю rsync с параметром --delete-before, через пару секунд уничтожаю rsync, чтобы у него было достаточно времени для удаления, а затем запускаю параллельные команды rsync. Это все немного хак, но это должно сработать. Тем не менее, когда я запускаю команду rsync с параметром --dry-run, я вижу, что он будет удалять файлы из цели, которые все еще существуют в источнике.

Это команда rsync, которую я запускаю:

rsync -av --delete-before --dry-run -P /some/folder/structure/ remotebackup.machine.com::backup/somefolder/

Выход которого:

building file list ...
415 files to consider
deleting fiFI.20150914.1317
deleting fiFI.20150914.1316
deleting my.20150914.1317
./
bareos/
bareos/my.20150917.1230
bareos/prod.20150918.0530
bareos/front01.20151101.0545
bareos/my.20160224.1504
bareos/fiFI.20150914.1316
bareos/fiFI.20150914.1317
bareos/fiFI.20150915.1311
bareos/fiFI.20150920.1230
bareos/fiFI.20150921.1231
bareos/fiFI.20150922.1230
bareos/fiFI.20151101.1230
<snip>

Как вы можете видеть, rsync намеревается удалить некоторые файлы fiFI, но позже он намерен передать те же файлы. Это отличается от того, что руководство rsync, по-видимому, заявляет --delete-before должен делать (удалять только тогда, когда файл больше не существует в источнике) и будет довольно неэффективно -> необходимо передавать больше данных.

Я проверил, что файлы действительно все еще существуют в источнике и в месте назначения, поэтому в моем ожидании он должен просто передать обновления, а не удалять целевой файл первым.

Из-за объема данных, которые я пытаюсь передать (5 ТБ), и необходимости распараллелить эту передачу (из-за пропускной способности), невозможно выполнить обычное удаление с непараллельным rsync. Я посмотрел на другие методы синхронизации данных, но вернулся из этого. Rsync - очень надежный инструмент, и он должен справиться с этим. Он ведет себя не так, как я ожидаю, и кажется, что он ведет себя не так, как говорится в руководстве.

Это нормальное поведение? Я делаю что-то неправильно? Почему это происходит (удалить перед передачей)?

Интересно, что если я запустил начальную rsync, которая удаляет файлы и распаковывает их, а затем снова запускает ту же самую rsync, файлы снова удаляются и передаются снова.

2 ответа

Решение

Я понял, ничего плохого в rsync. На втором этапе, когда я передаю данные параллельно, я использовал это:

find /some/folder/structure/ -type f -mmin +60 | parallel -j4 'echo "starting `date` {}";rsync -av --no-compress --no-whole-file --quiet {} somehost.com::backup/somefolder/;echo "done `date` {}"'

это приводит к тому, что все файлы записываются в "somefolder" в месте назначения, независимо от какой-либо структуры каталогов. При следующем запуске скрипта 1-й шаг находит файлы там, где их не должно быть, поэтому он удалит их. И тогда это передаст их. 1-й rsync перенесет их в правильное место, но этот шаг предназначен только для удаления файлов, которые не существуют и уничтожаются. Затем запускается 2-ая rsync, но, поскольку она неверна, файлы будут помещены в неправильное место. Промыть и повторить.

Исправление заключается в использовании относительных путей, таких как это:

find /some/folder/structure/ -type f -mmin +60 | sed 's/\some\/folder\/structure\/\(.*\)/\some\/folder\/structure\/.\/\1/g' | parallel -j4 'echo "starting `date` {}";rsync -av --no-compress --no-whole-file --quiet {} somehost.com::backup/somefolder/;echo "done `date` {}"'

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

Во-первых, прямой ответ: согласно официальной документации rsync, я не могу найти явный ответ; это зависит от интерпретации. Тем не менее, я считаю, что вы не видите правильное поведение.

В любом случае, у меня есть рекомендация.

На https://meta.stackexchange.com/questions/17204/six-simple-tips-to-get-reputation-fast-on-any-stack-exchange-site, в частности , ответ Мандара Шинде, вам, вероятно, лучше разбить rsync на две фазы: список файлов (через --dry-run), а затем синхронизировать.

Используя его пример, сделайте что-то вроде:

rsync -avzm --stats --safe-links --ignore-existing --dry-run --human-readable /some/folder/structure/ remotebackup.machine.com::backup/somefolder/ > /tmp/transfer.log

затем:

cd /some/folder/structure/ && (cat /tmp/transfer.log | parallel --will-cite -j 5 rsync -avzm --relative --stats --safe-links --ignore-existing --human-readable {} remotebackup.machine.com::backup/somefolder/ > result.log)
Другие вопросы по тегам