Копируем с RSync: основные примеры синхронизации файлов

RSync это быстрый и чрезвычайно универсальный инструмент для синхронизации (копирования) файлов. Его самое основное преимущество это передача только изменившиеся части файла, а не файла целиком, что несомненно отражается на скорости копирования/синхронизации. А если при копировании произойдет какой-то сбой, то достаточно перезапустить команду и копирование будет продолжено с того же места.

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

Сам сервис работает на SSH протоколе по умолчанию, но может работать и на собственном протоколе rsyncd, но обо всем по порядку.

Установка

По умолчанию rsync есть не везде, поэтому если вы получили ошибку "bash: rsync: command not found" - значит его нужно установить (как на локальной, так и на удаленной машине):

# для debian 
apt install rsync

# для centos
yum install rsync

Базовый синтаксис

rsync <опции> <что копируем с компьютера> <пользователь@хост:/куда_копируем>

Основные опции RSync

Ниже перечислены только основные опции, которые чаще всего помогали в работе. Я попытался разделить их на некоторые подгруппы для удобства их использования.

Базовые опции:

-n, --dry-run – что-то типа тестового режима, указывает не осуществлять никаких передач, а только сообщать о тех действиях, которые могли бы произойти.
-a, --archive – архивный режим, включает рекурсивное копирование и сохранение прав и владельца (эта опция включает в себя опции rlptgoD, они будут описаны следующими). Учтите, эта опция не сохраняет жесткие ссылки.
-r, --recursive – рекурсивный режим (копирование всех директорий и файлов в них).
-l, --links – копировать символьные ссылки как символьные ссылки.
-p, --perms – сохранять права для файлов. Без указания этой опции каждый новый файл получает те права доступа, что имеет исходный с учетом umask, действующей на приемной стороне, в то время как все другие (включая обновляемые) сохраняют свои уже существующие разрешения (это то же поведение, что имеют другие утилиты копирования файлов, такие как cp).
-t, --times – обновлять время модификации файла на приёмной стороне (при отсутствии этой опции или -a становиться неэффективной оптимизация передачи по времени изменения файлов).
-g, --group – сохранять группу пользователя. Если удаленная сторона не действует из-под супер-пользователя, то сохранятся только те значения групп, членом которых является пользователь приемной стороны, т.е. имеет значение имя группы, а не ее id.
-o, --owner – сохранять владельца на приемной стороне в точности с оригиналом. На большинстве систем только супер-пользователь имеет право устанавливать владельца файла. Нужно заметить, что если удаленный демон действует в chroot-окружении, то подразумевается наличие параметра --numeric-ids (он описан ниже), потому что на удаленной стороне в этом случае нет доступа к именам пользователей в /etc/passwd.
-D, --devices – сохранять файлы устройств (root only).

Работа с файлами:

-u, --update – не перезаписывать более новые файлы: указывает пропускать любые файлы, уже существующие на приемной стороне с более поздней датой, чем у исходных файлов.
--delete – удалять файлы, которых нет в источнике (полезно для создания точной копии).
--ignore-errors – продолжать копирование и удаление после появления ошибок (При удалении (--delete) форсирует процесс и игнорирует любые ошибки, даже ошибки ввода-вывода.)
--exclude – исключить файлы (подробно описано ниже).
--include – не исключать файлы (подробно описано ниже).
-F – опция которая заставляет искать файл .rsync-filter, в котором настраиваются фильтры (exclude/include). Если опция указана дважды то будет исключен и сам файл .rsync-filter.
-x, --one-file-system – не переходить границ файловой системы при рекурсивном копировании. Это полезно при необходимости копирования только одной файловой системы.
-R, --relative – использовать относительные пути при создании символических ссылок. Это значит, что посылаются полные пути, указанные в командной строке, а не последние части имен файлов. На практике это полезно, когда Вам нужно послать несколько различных каталогов за раз.
-H, --hard-links – пересоздать жесткие ссылки на конечной стороне в соответствии с тем, что имеется на исходной. Без этого параметра жесткие ссылки обрабатываются как обычные файлы.
-L, --copy-links – Если обнаружена символьная ссылка, то на приемную сторону копируется файл, на который она указывает, а не такая же символьная ссылка.
--numeric-ids – не транслировать имена владельца и группы в цифровые UID и GID, оставить на удалённой стороне номера как есть.
Вместо имен групп и пользователей посылаются их числовые id и ставятся в соответствие друг другу на обоих концах.
По умолчанию rsync использует имена групп и пользователей для определения владельца файлов. Специальные uid 0 и gid 0 никогда не отображаются через имена пользователей/групп, даже если не указана --numeric-ids.
Если исходная система работает в ограниченном chroot-окружении или если пользователь или группа не существуют на приемной стороне, то используются исходные числовые id.
-m, --prune-empty-dirs – не копировать пустые директории. 

Настройка синхронизации/подключения/передачи файлов:

-c, --checksum – использование сверки по контрольным суммам, а не по времени изменения и размеру файлов.
--size-only – сверять только размер файлов (по умолчанию проверяется размер и время модификации).
-z, --compress – компрессия данных при передаче (реализуется gzip).
-e,--rsh="command" – опция позволяет выбрать альтернативный протокол подключения между удаленной и локальной машинами.
--max-size – максимальный размер файла для передачи.
--bwlimit — ограничение скорости для передачи файлов (Kbit/s).
--partial – По умолчанию rsync будет удалять все частично-переданные файлы в случае сбоя передачи. Если этот параметр указан, то rsync будет сохранять частично-переданные файлы, что может сократить время копирования при повторном запуске.
-P – данная опция включает в себя опцию --partial и --progress.

Отображение/результат:

--progress – выводить прогресс передачи файлов.
--stat – показать статистику передачи.
-v, --verbose – вывести подробную информацию о процессе: один -v будет выдавать список переданных файлов и итог в конце, два -v выдает детали о пропущенных файлах и более подробный итог, больше -v полезно для отладки.
-q, --quiet – минимальная информация.

Опции полезные для создания инкрементальных резервных копий:

-b, --backup – создавать резервные копии ранее существовавших файлов до начала копирования на принимающей стороне. По умолчанию файлам добавляется суффикс ~, а если указана директория (--backup-dir), то суффикс не добавляется.
--backup-dir=.. – указывает каталог, куда сохранять резервные копии.
--suffix=.. – опция позволяет указать свой суффикс.

Теперь пройдемся по базовым примерам.

Как скопировать/синхронизировать файлы у себя на компьютере

Вот так:

rsync -av /home/user/Downloads/files/ /home/user/Downloads/copyfiles

Данная команда копирует файлы (т.е. содержимое) из каталога /home/user/Downloads/TEMP/files/ в каталог /home/user/Downloads/TEMP/copyfiles.

Важный момент:

  • если в конце пути до источника (каталога) нет слэша, то будет скопирован сам каталог (в примере выше это files).
  • если слэш указан, то будет скопировано содержимое каталога (т.е. то, что внутри files, из примера выше)

В случае необходимости скопировать несколько каталогов и файлов за раз в каталог, которого еще не существует, можно выполнить эту команду:

rsync -av ./2021 ./logo.svg.png ./copy2021 ./copydir

Находясь в нужном каталоге, мы скопировали каталог 2021, файл logo.svg.png и еще один каталог copy2021 в несуществующий ранее каталог copydir.

Вот как это выглядит наглядно:

rsync -av ./2021 ./logo.svg.png ./copy2021 ./copydir
sending incremental file list
created directory ./copydir
logo.svg.png
2021/
2021/filefromsrv
2021/filestorage.png
2021/login.png
2021/mainweb.png
2021/motiondetection.png
2021/motioneye-movies.png
2021/motioneye-recordetmovies.png
copy2021/
copy2021/just-file.txt

sent 723,033 bytes  received 349 bytes  1,446,764.00 bytes/sec
total size is 721,629  speedup is 1.00

Получается это не плохая альтернатива cp :)

Как скопировать/синхронизировать с компьютера на удаленный сервер

Вот так

rsync -av 2021 [email protected]:/home/user/

Важно указывать полный путь на удаленном сервере, иначе rsync попытается скопировать каталог "2021" в корень удаленного сервера.
Еще важно указывать полный путь до удаленного сервера, так как, к примеру, копируя файл "file.txt" на сервер указав путь /home/user/somedir, каталог somedir не будет создан, вместо этого файл file.txt скопируется на сервер под именем somedir. Чтобы избежать этого используйте путь полный путь /home/user/somedir/.

Если мы хотим немного сжать файлы при передачи (к примеру у нас медленный интернет), можно использовать ключ -z:

rsync -avz 2021 [email protected]:/home/user/

Но важно понимать, что сжатие имеет смысл использовать там где это нужно, так как в новых версиях ssh уже использует сжатие передаваемых данных, тратить ресурсы CPU не стоит, особенно на слабых машинах или NAS серверах.

Как скопировать/синхронизировать с удаленного сервера на компьютер

Вот так:

rsync -av [email protected]:/home/user/filefromsrv ./

В данном примере мы копируем файл filefromsrv в каталог, в котором находимся.

Как указать другой порт ssh и ключ?

С помощью опции -e (она же --rsh). Вот как скопировать файл с компьютера на сервер у которого не стандартный ssh порт:

rsync -av -e "ssh -p 2013" ./filefrompc  [email protected]:/home/user/

А вот как можно указать ключ авторизации и порт:

rsync -av -e "ssh -p 2013 -i ~/.ssh/id_rsa" ./filefromsrv  [email protected]:/home/user/mydir/

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

Пример конфига:

$ cat ~/.ssh/config
Host srv
   HostName 10.10.20.7
   Port 2013
   User user

Пример команды:

rsync -av ./filefromsrv srv:/home/user/somedir/

Я хочу видеть прогресс копирования/синхронизации

Стоит иметь в виду, что по умолчанию rsync копирует файлы без какого-либо вывода.

В примерах выше я использую ключ -v для того, чтобы видеть какие файлы были скопированы и получить некий отчет о проделанных действиях. Вот пример:

rsync -av ./somedir [email protected]:/home/leo/
sending incremental file list
somedir/
somedir/Screenshot from 2021-01-22 17-42-17.png
somedir/Screenshot from 2021-01-24 02-17-17.png

sent 1,996,838 bytes  received 58 bytes  3,993,792.00 bytes/sec
total size is 2,041,319  speedup is 1.02

Если мы хотим видеть наиболее интересный вывод, то нам в этом поможет ключ --progress. Вот пример:

rsync -aP ./somedir [email protected]:/home/user/
sending incremental file list
somedir/
somedir/Screenshot from 2021-01-22 17-42-17.png
        194,291 100%   51.35MB/s    0:00:00 (xfr#1, to-chk=1/3)
somedir/Screenshot from 2021-01-24 02-17-17.png
      1,847,028 100%   21.22MB/s    0:00:00 (xfr#2, to-chk=0/3)

Некоторые могут советовать ключ -P, но имейте в виду, -P включает в себя ключ --partial и --progress одновременно (что в целом не так страшно).

Как ограничить скорость передачи файлов?

Нужно указать опцию --bwlimit=SPEED, где SPEED это скорость в Кбайт в секунду:

rsync -avP --bwlimit=100 ./somedir [email protected]:/home/leo/

Полезно бывает на слабом интернете с большими файлами.

Как исключить некоторые файлы или включить определенный тип файлов?

В rsync можно создавать достаточно гибкие исключения, например, делая резервную копию домашней директории на linux мы не ходим копировать разный кеш или содержимое корзины. Вот пример, в котором я исключаю две директории:

rsync -av --exclude={'user/.local/share/Trash','user/.cache'} /home/user [email protected]:/home/user/bkp/

Конечно можно указать одну директорию:

rsync -av --exclude=.git /var/www/site [email protected]:/home/user/bkp/

Еще мы можем исключить файлы с определенным расширением:

rsync -av --exclude="*.tmp" /var/www/site [email protected]:/home/user/bkp/

Саму опцию мы можем использовать несколько раз:

rsync -av --exclude="*.tmp" --exclude="tmp/*" --exclude="*~" /var/www/site [email protected]:/home/user/bkp/

Для копирования определенного типа файлов (да и не только) мы можем использовать опцию --include. Используется она точно так же, как и exclude. Вот пример, в котором я загружаю на сервер только все файлы с расширением .sql:

rsync -av --exclude="*.sql" ./projectname [email protected]:/home/user/sqlbkp/

Исключения с помощью .rsync-filter

Для более гибкой настройки копирования (в случае регулярного копирования это будет очень полезно) все исключения/включения можно оформить в файле .rsync-filter (это появилось в более поздних версиях rsync).

Попробую объяснить подробно на примере, как и что мы можем исключать (спасибо этому блогу за хорошее описание).
Допустим, у меня есть такой каталог (somedir), в котором я хочу исключить (красная стрелка) или оставить (зеленая стрелка) некоторые файлы/каталоги:

Ниже приведен один из примеров настройки исключений в файле .rsync-filter с комментариями:

cat .rsync-filter 
# исключаем только каталог .cache (не будут исключены каталоги work/lo*/.cache и dir2/.cache)                                                                        
- /.cache
# исключаем все каталоги Trash во всех папках
- /**/Trash/
# исключаем каталог Cache в каталогах .mysoft/soft*/
- /.mysoft/*/Cache
# исключаем файл pass.md
- pass.md
# исключаем все файлы с расширением .tmp
- *.tmp
# исключаем весь каталог example
- /example/
# Оставляем каталог Trash в каждом каталоге work/lo*/..
+ /work/**/Trash/

Для того, чтобы rsync заметил файл .rsync-filter, достаточно указать опцию -F:

rsync -avF ./somedir 10.10.20.15:/home/leo/

В итоге на сервер будут скопированы только эти файлы:

Кстати, если мы не хотим чтобы сам .rsync-filter не копировался, то -F нужно будет указать дважды

Другие полезные опции

--delete / --delete-after / --del (--delete_during)

Если мы делаем ежедневные резервные копии и не хотим засорять удаленный сервер лишними файлами (которых уже нет в источнике), то мы можем использовать опцию --delete:

rsync -avz -e "ssh -p 2013" --delete ./somedir [email protected]:/home/bkp/

В результате будет удален файл, которого больше нет в директории источника (в somedir):

rsync -avz -e "ssh -p 2013" --delete ./somedir [email protected]:/home/bkp/
[email protected]'s password: 
sending incremental file list
deleting somedir/lolo
somedir/

sent 159 bytes  received 77 bytes  67.43 bytes/sec
total size is 2,041,319  speedup is 8,649.66

По умолчанию, rsync сначала выполняет удаление файлов перед копированием для уверенности, что хватит свободного места на приемной стороне (т.е. использует по умолчанию --delete-before). Если мы хотим удалять файлы после копирования, используйте параметр --delete-after.

Если мы хотим хотим удалять файлы в процессе передачи, а не перед, то можно использовать опцию --del (--delete_during). Это поможет сэкономить немного ресурсов и времени.

Кстати, это не все "delete" параметры, которые есть, вот их полный список с кратким описанием:

--del – an alias for --delete-during
--delete – delete extraneous files from dest dirs
--delete-before – receiver deletes before transfer (default)
--delete-during – receiver deletes during xfer, not before
--delete-delay – find deletions during, delete after
--delete-after – receiver deletes after transfer, not before
--delete-excluded – also delete excluded files from dest dirs

А если вам по какой-то причине не нужно обновлять файлы на принимающем сервере, вместо опции --del.. можно использовать опцию --ignore-existing.

--no-perms --no-owner --no-group

Иногда нам может потребоваться не переносить атрибуты (права файлов, пользователя и группу пользователя). Для этого мы можем воспользоваться опциями --no-p --no-o --no-g (оно же --no-perms --no-owner --no-group):

rsync -avz -e "ssh -p 2013" --no-p --no-o --no-g ./somedir 

Важно соблюдать порядок (особенности работы "--no-OPTION" в rsync).

--inplace

По умолчанию rsync, при копировании существующего файла создает его новую версию, а потом заменяет старый файл на новый. Это сделано для того, чтобы исходный файл не пострадал в случае каких-то перебоев. Данная опция позволяет изменить это поведение таким образом, чтобы rsync сразу начал перезапись старого файла. Опция полезна при копировании больший файлов на одном компьютере:

rsync -av --inplace ./Видео.mp4 ./vidinplace.mp4

-W, --whole-file

Эта опция будет полезна, если мы копируем файлы с нагруженного или слабого сервера, так как она отключает дифференциальный алгоритм rsync'а и с ним весь файл передается как есть, целиком, не тратя время CPU на вычисления.

Что в итоге?

Я постарался описать наиболее частые примеры использования rsync, и сказу сразу: это только минимум того, что может эта утилита.

Если вы где-то нашли ошибку, или есть еще какие-то интересные способы использования rsync - пишите, я добавлю их в статью ;).

Источники: