Можно подумать, что --link-dest
использование идентичного файла будет работать во всех случаях. Но это не так, когда файл существует, даже если файл устарел / имеет другое содержимое.
Из-за этого на странице руководства rsync --link-dest
:
«Этот параметр лучше всего работает при копировании в пустую целевую иерархию, поскольку rsync рассматривает существующие файлы как окончательные (поэтому rsync никогда не просматривает каталоги link-dest, когда целевой файл уже существует )»
Это означает, что если y/file
существует так же, как источник, и z/file
устарел,
rsync -a --del -link-dest=y source:/file z
приведет к ДВУМ инодам (и в два раза дискового пространства) используются, y/file
и z/file
, которые будут иметь такое же содержание и временную метку.
Я сталкивался с этим, потому что я делаю ежедневные резервные копии в основном с помощью этого сценария, запускаемого один раз в день
mv $somedaysago $today;
yest=$today; today=`date +%Y%m%d`;
rsync -avPShyH --del --link-dest=../$yest host:/dirs $today
Поскольку мои резервные копии занимают до 10 миллионов файлов, выполнение rm -rf $olddir; rsync source:$dir newdir
может занять слишком много времени (особенно, если в день изменяется только 0,5% файлов, что приводит к удалению и созданию 10-миллиметровых записей dir только для обработки 50 тыс. Новых или измененных файлов, что может привести к резервные копии не завершены вовремя на следующий день).
Вот демонстрация ситуации:
a
наш источник, 1
через 4
наши нумерованные резервные копии:
$ mkdir -p 1 2; echo foo > 1/foobar; cp -lrv 1/* 2
`1/foobar' -> `2/foobar'
$ ls -i1 */foobar
1053003 1/foobar
1053003 2/foobar
$ mkdir a; echo quux > a/foobar
$ mv 1 3; rsync -avPhyH --del --link-dest=../2 a/ 3
sending incremental file list
./
foobar
5 100% 0.00kB/s 0:00:00 (xfer#1, to-check=0/2)
sent 105 bytes received 34 bytes 278.00 bytes/sec
total size is 5 speedup is 0.04
$ ls -i1 */foobar
1053003 2/foobar
1053007 3/foobar
1053006 a/foobar
$ mv 2 4; rsync -avPhyH --del --link-dest=../3 a/ 4
sending incremental file list
./
foobar
5 100% 0.00kB/s 0:00:00 (xfer#1, to-check=0/2)
sent 105 bytes received 34 bytes 278.00 bytes/sec
total size is 5 speedup is 0.04
$ ls -il1 */foobar
1053007 -rw-r--r-- 1 math math 5 Mar 30 00:57 3/foobar
1053008 -rw-r--r-- 1 math math 5 Mar 30 00:57 4/foobar
1053006 -rw-r--r-- 1 math math 5 Mar 30 00:57 a/foobar
$ md5sum [34a]/foobar
d3b07a382ec010c01889250fce66fb13 3/foobar
d3b07a382ec010c01889250fce66fb13 4/foobar
d3b07a382ec010c01889250fce66fb13 a/foobar
Теперь у нас есть 2 резервные копии a/foobar
, которые идентичны во всех отношениях, включая временную метку, но занимают разные inode.
Кто-то может подумать, что было бы решение --delete-before
, которое убивает выгоду от инкрементного сканирования, но это также не помогает, так как файл не будет удален, но будет использоваться в качестве основы в случае, если инкрементное копирование возможно.
Можно еще предположить, что мы можем отключить хеджирование с инкрементным копированием --whole-file
, но это не поможет алгоритму, нет способа получить то, что мы хотим.
Я считаю это поведение еще одной ошибкой в rsync, где полезное поведение может быть истолковано из тщательного выбора различных аргументов команды, но желаемый результат недоступен.
К сожалению, решение будет состоять в том, чтобы перейти от одиночной rsync как атомарной операции к пробному запуску с -n
регистрацией, обработкой этого журнала в качестве входных данных, чтобы вручную предварительно удалить все измененные файлы, а затем запустить, rsync --link-dest
чтобы получить то, что мы хотим - большой kludge по сравнению с одним чистым rsync.
Приложение: попытался предварительно связать $yesterday
и $today
на сервере резервного копирования перед резервным копированием с использованием производственных ящиков с rsync --link-dest=../$yesterday $yesterday/ $today
- но с тем же результатом - любой файл, который существует любым способом, даже длиной 0, никогда не будет удален и удален из ссылки, а не целиком новая копия будет сделана из источника с новым инодом и занимая больше места на диске.
Рассматривается pax(1)
как возможное решение для предварительной компоновки перед резервным копированием.
--delete-after
это хорошо, но не имеет отношения к проблеме под рукой. Файлы, отсутствующие в источнике, будут удалены после завершения копирования. Проблема, которую я объясняю, связана с резервным копированием, которое выполняется сегодня, которое идентично вчерашнему, но со старым существующим устаревшим файлом, который не связан со вчерашним индексом, но хранится как новый файл в два раза больше дискового пространства, чем вчера идентичная копия считается.
rsnapshot
? Кроме того, подумайте над написанием небольшого скрипта, чтобы связать «идентичные» файлы. Я делаю оба на моих системах.
hardlink(1)
медленный (в 15 раз медленнее, чем сканирование метаданных rsync); pax
быстрее, но бьет головки жестких дисков, сравнивая старые резервные копии с новыми. rsync -n
получить дельта-список означает дважды поработать с производственными серверами (сканирование 10M-файлов гораздо более важно, чем копирование 50K-изменений). Я отправлю список опций в rsync, чтобы разрешить это.
--delete-after
в этом сценарии использования, что не так с этим?