Rsync с --checksum из локального в локальный?

Сначала я попытаюсь немного разобраться в проблеме. У нас есть проект, который строится в большом дереве файлов. Сборка составляет несколько сотен МБ, содержит множество (мелких) файлов, лишь небольшая часть которых меняется между сборками. Мы хотим сохранить немного истории этих сборок, и для этого мы хотим жестко связать файлы, которые не меняются между сборками. Для этого мы используем rsync(как более могущественный брат cp), из локального источника в локальную мишень с опцией --link-destдля выполнения магии жесткого связывания.

Это отлично работает для инкрементных сборок: большинство файлов не затрагиваются, и rsyncправильно выполняет трюк с жесткой ссылкой. С полной перекомпиляцией сборок (что мы должны делать по причинам, которые здесь не уместны), кажется, что все работает не так, как ожидалось. Из-за перекомпиляции все файлы получают новую метку времени, но с точки зрения содержимого большинство файлов по-прежнему совпадают с предыдущей сборкой. Но даже несмотря на то, что мы используем rsyncс опцией --checksum(поэтому rsync«синхронизирует»/жесткие ссылки на основе содержимого, а не размера файла + метки времени), ничто больше не становится жестко связанным.

Иллюстрация

Я попытался выделить/проиллюстрировать проблему с помощью этого простого (bash) скрипта:

echo "--- Start clean"
rm -fr src build*

echo "--- Set up src"
mkdir src
echo hello world > src/helloworld.txt

echo "--- First copy with src as hardlink reference"
rsync -a --checksum --link-dest=$(pwd)/src src/ build1/

echo "--- Second copy with first copy as hardlink reference"
rsync -a --checksum --link-dest=$(pwd)/build1 src/ build2/

echo "--- Result (as expected)"
ls -ali src/helloworld.txt build*/helloworld.txt

echo "--- Sleep to have reasonable timestamp differences"
sleep 2

echo "--- 'Remake' src, but with same content"
rm -fr src/helloworld.txt
echo hello world > src/helloworld.txt

echo "Third copy with second copy as hardlink reference"
rsync -a --checksum --link-dest=$(pwd)/build2 src/ build3
# Using --modify-window=10 gives results as expected
# rsync -a --modify-window=10 --link-dest=$(pwd)/build2 src/ build3

echo "Final result, not as expected"
ls -ali src/helloworld.txt build*/helloworld.txt

Первый результат, как и ожидалось: все три копии жестко связаны (один и тот же inode)

30157018 -rw-r--r--  3 stefaan  staff  12 May 10 01:28 build1/helloworld.txt
30157018 -rw-r--r--  3 stefaan  staff  12 May 10 01:28 build2/helloworld.txt
30157018 -rw-r--r--  3 stefaan  staff  12 May 10 01:28 src/helloworld.txt

Конечный результат не такой, как ожидалось/желательно:

30157018 -rw-r--r--  2 stefaan  staff  12 May 10 01:28 build1/helloworld.txt
30157018 -rw-r--r--  2 stefaan  staff  12 May 10 01:28 build2/helloworld.txt
30157026 -rw-r--r--  1 stefaan  staff  12 May 10 01:28 build3/helloworld.txt
30157024 -rw-r--r--  1 stefaan  staff  12 May 10 01:28 src/helloworld.txt

Третья копия build3/helloworld.txtне имеет жесткой ссылки на копию из build2, даже если содержимое одинаковое, поэтому проверка контрольной суммы должна видеть это.

Вопрос

Кто-нибудь имеет представление о том, что здесь не так? Неужели мои ожидания ошибочны? Или rsync игнорирует --опция checksumпри синхронизации с локальной на локальную, например, потому что известно, что смотреть на числа inode разумнее, чем тратить время на контрольные суммы?

5
задан Stefaan 9 May 2012 в 23:52
поделиться