
Я использую rsync для копирования файлов с Linux на Mac через SSH.
Моя команда выглядит так:
rsync \
--exclude FOO \
--exclude BAR \
-e ssh \
-rclpvih \
--delete \
--stats \
/local/dir/ \
host:/remote/dir/
И вывод выглядит так:
building file list ... done
...
<fc.T...... core/FileRecordingProcessor.cpp
<fc.T...... core/Pipeline.hpp
...
Number of files: 4,910 (reg: 4,401, dir: 509)
Number of created files: 0
Number of regular files transferred: 35
Total file size: 332.34M bytes
Total transferred file size: 2.62M bytes
Literal data: 0 bytes
Matched data: 2.62M bytes
File list size: 196.59K
File list generation time: 0.457 seconds
File list transfer time: 0.000 seconds
Total bytes sent: 209.72K
Total bytes received: 12.03K
sent 209.72K bytes received 12.03K bytes 147.83K bytes/sec
total size is 332.34M speedup is 1,498.70
Даже если локально ничего не изменилось, rsync передает один и тот же (под)набор файлов при каждом вызове.
Эти файлы — лишь малая часть всего дерева. Другие файлы не пересылаются, если они действительно не изменены. Количество пересылаемых файлов всегда равно 35. Все они имеют <fc.T......
флаги.
Файлы выглядят одинаково на локальных и удаленных машинах.
Местный:
$ ll core/Pipeline.hpp
-rw-r--r-- 1 victor victor 5.1K Nov 2 18:24 core/Pipeline.hpp
$ md5sum core/Pipeline.hpp
7604940d777322a587d2fe2fa12c1183 core/Pipeline.hpp
Удаленный:
$ ll core/Pipeline.hpp
-rw-r--r-- 1 victor staff 5.1K Nov 3 18:20 core/Pipeline.hpp
$ md5sum core/Pipeline.hpp
7604940d777322a587d2fe2fa12c1183 core/Pipeline.hpp
Владелец, группа и время не совпадают, но rsync не настроен на их сохранение, а настроен наиспользовать контрольные суммы.
Время на двух машинах не синхронизировано.
решение1
Одним из случаев, когда это может произойти, является передача файлов rsync между файловой системой, чувствительной к регистру (обычно Linux), и файловой системой, нечувствительной к регистру (обычно Windows и MacOS).
Если два синхронизированных пути (например, d/x
и d/X
) совпадают после условного преобразования, скажем, в нижний регистр, то rsync этого не замечает и может передать d/x
, а затем перезаписать тот же файл назначения с помощью d/X
.
Если файлы не содержат одни и те же данные и имеют одинаковую временную метку, файлы всегда будут обновляться при будущих запусках rsync.
Предлагаю проверить, не является ли разница в верхнем/нижнем регистре причиной того, что rsync ошибочно пересылает файлы. Одна полезная команда Linux:
find . | tr '[:upper:]' '[:lower:]' | LC_ALL=C sort | LC_ALL=C uniq -d
решение2
Вы пропустили либо флаг --archive
( -a
), либо --times
( -t
). Без одного из них rsync
не будет отслеживаться время изменения, и поэтому он не сможет обойти файлы, которые выглядят так, как будто они уже были скопированы
Вы также явно указываете rsync
на необходимость использования контрольных сумм для проверки того, что файлы были скопированы, так что именно это и rsync
происходит.
В общем, флаг --archive
( -a
) сделает практически все, что вам нужно:
rsync --exclude FOO --exclude BAR -avi --delete --stats /local/dir/ host:/remote/dir/
Возможно, вы захотите -H
сохранить жесткие ссылки (если они у вас есть), а также -AX
сохранить списки управления доступом и расширенные атрибуты (если они у вас есть).
решение3
TL;DR: Если вы используете macOS, попробуйте использовать /usr/bin/rsync вместо rsync с открытым исходным кодом, который могут установить "brew" или "nix" или другие системы. Собственный rsync лучше понимает специальную файловую систему Apple и не будет повторно копировать неизмененные файлы.
Более длинная версия...
Ситуация, когда это может произойти, это если версия, rsync
которую вы используете, не поддерживает ситуации, специфичные для ОС. Она будет повторно копировать файлы, которые, по ее мнению, были изменены, но на самом деле нет.
Например, на моем Mac установлено 2 версии rsync
:
$ which -a rsync
/usr/local/bin/rsync
/usr/bin/rsync
/usr/local/bin/rsync
это версия 3.2.4, которая поддерживает протокол версии 31. Я установил ее с помощью «brew».
/usr/bin/rsync
— это версия, предоставленная Apple, которая является ответвлением версии 2.6.9 (гораздо более старой) и поддерживает протокол версии 29. Apple улучшила эту версию для поддержки функций файловой системы, специфичных для macOS.
Когда я использую -c
версию с открытым исходным кодом, она перекопирует файлы, которые не были изменены. У rsync, предоставляемого Apple, этой проблемы нет.
Хотя между версиями протокола 29 и 31 есть много оптимизаций, вы, вероятно, не пропустите их. Правильное использование rsync от Apple, вероятно, важно.
решение4
В итоге я переключился наунисондля синхронизации между Linux и macOS (и Windows):
unison \
-servercmd /usr/local/bin/unison
-ignore "Name FOO" \
-ignore "Name BAR" \
-auto \
-batch \
-force /local/dir/ \
/local/dir/ \
ssh://host/remote/dir/