Найти тему
MasterTonLab Hi Tech

RSync - Синхронизация двух директорий на одном компьютере (Сервере)

Оглавление

В этой статье я на конкретных практических примерах покажу как работать с утилитой RSync в Linux.
RSync - это очень быстрый и мощный инструмент для работы с файлами и каталогами как на локальном компьютере, так и на удалённом сервере.

С одной стороны RSync - это лёгкая (в плане потребления ресурсов) и многофункциональная утилита с широкими возможностями - незаменимый инструмент системного администратора, с другой же стороны для новичков и не сильно продвинутых пользователей Линукс RSync может показаться очень сложным, замудрёным и непонятным.
Поэтому мы будем здесь разбирать простые примеры и на них учиться работать с RSync.
Для этого возьмём практическую и довольно часто встречающуюся задачу - синхронизацию файлов и папок на локальном компьютере (сервере). Это бывает нужно не только сисадмину на сервере, но и обычным пользователям на домашнем/рабочем компьютере или ноутбуке. Например, надо перенести рабочий проект (несколько файлов и папок) на флешку, потом на домашний компьютер, дома поработать и затем только новые или измененные файлы снова скопировать на флешку, ну а после этого сделать синхронизацию с рабочим компьютером. Или, например, синхронизация своей личной библиотеки между ноутбуком и домашним компьютером, причём, какие-то книги могут быть изначально закачаны на ноутбук, а какие-то на домашний компьютер. И надо это всё привести к единообразию: чтобы там и там были все книги. Или, например, копирование своего фотоальбома на внешний жесткий диск.
Как видим, задача синхронизации встречается очень часто и может иметь самое разное практическое применение.

-2

Вы можете как раз взять для себя именно ту задачу, которую вам и необходимо решить. А я для примера возьму вот такую задачу: создание архива всех установленных программ (пакетов), чтобы они всегда были под рукой и в случае переустановки системы не нужно было их заново выкачивать. Делать это сохранение мы будем по мере установки новых программ (пакетов) или же обновления уже имеющих. Практически в каждом дистрибутиве Линукс имеется специальный каталог, в котором временно хранятся все скачанные пакеты. В дистрибутивах семейства Дебиан (Debian, Ubuntu, Lubuntu, Linux Mint и другие) это будет каталог: /var/cache/apt/archives
Вот так сейчас этот каталог выглядит на моей тестовой машине:

Локальный репозиторий пакетов Линукс
Локальный репозиторий пакетов Линукс

Создадим папку на другом диске для копирования туда этих файлов и дальнейшей синхронизации:
$ mkdir /media/testuser01/SecondDisk/PackagesBackup

Сейчас эта папку пустая. Сделаем первую синхронизацию.
$ rsync -vh --progress /var/cache/apt/archives /home/myusername/PackagesBackup

-4

Здесь я использовал ключи (options):
-v (verbose) - вывод более детальной информации о производимых действиях
-h (human-readable) - вывод чисел в удобочитаемом формате
--progress - показать прогресс во время передачи
Первый путь "/var/cache/apt/archives" -
каталог-источник (source)
И вот здесь внимательный читатель конечно же заметил, что второй путь ошибочный. "/home/myusername/PackagesBackup" - это не существующий путь и подкаталога "/myusername" в каталоге "/home" не существует (также как не существует и пользователя с таким именем).
Да, я намеренно ввёл неверный путь
каталога-приёмника (destination), так как мы сейчас смотрим, учимся, изучаем и нам важно знать не только как делать правильно, но и что произойдет, если ввести что-то не верно. А ошибки в ключах, опечатки часто бывают и в реальной практике. Поэтому мы в некоторых случаях будем намеренно создавать ошибочные ситуации, чтобы знать что будет происходить, а также чтобы по соответствующей реакции системы и сообщениям об ошибках сразу видеть в чём именно ошибка и как её исправить.
Система нам в этом примере совершенно верно вывела сообщение об ошибке: "failed: No such file or directory". Т.е. не удалось выполнить операцию: нет такого файла или каталога.

Теперь введем команду с частично правильным путём каталога-приёмника:
$ rsync -vh --progress /var/cache/apt/archives /media/testuser01/PackagesBackup

-5

Здесь уже путь "/media/testuser01" существует, а вот подкаталога "/PackagesBackup" в нём нет. И система не выдаёт столь грозных сообщений об ошибках, но и действий никаких не производит: никакие файлы или каталоги никуда не копируются.

Ну чтож, давайте теперь уже введём наконец команду с правильным путём каталога-приёмника:
$ rsync -vh --progress /var/cache/apt/archives /media/testuser01/SecondDisk/PackagesBackup

-6

Но и в этом случае никаких действий произведено не было, никакие файлы или каталоги никуда не скопировались. Хотя путь задан верно и простая проверка командой ls покажет, что такой путь существует.
Так в чём же тогда дело?
Внимательно смотрим на предупреждение, которое выдала нам система: "skipping directory archives" - т.е. каталог "archives" был пропущен.
И дел здесь в том, что команда rsync синхронизирует прежде всего файлы, а не каталоги (каталоги тоже, но об этом ниже). А мы в качестве источника не задали никаких файлов, а указали только каталог. Чтобы задать файлы нужно указать вот такой путь источника: "/var/cache/apt/archives/*" Т.е. выбрать все файлы в подкаталоге "archives". А полностью команда будет выглядеть так:
$ rsync -vh --progress /var/cache/apt/archives/* /media/testuser01/SecondDisk/PackagesBackup

-7

И сразу же команда заработала, файлы скопировались. Правда тоже есть предупреждения и сообщения об ошибках - их мы разберем чуть позже. А пока проверим, точно ли все файлы скопировались в нашу папку "PackagesBackup".

-8

Да, действительно, почти все файлы скопировались. Если мы вернёмся в начало и посмотрим снова на содержимое каталога-источника (/var/cache/apt/archives), то увидим, что там есть ещё один файл "lock" и подкаталог "partial". Собственно предупреждение "skipping directory partial" как раз и говорит о том, что этот каталог был пропущен. Что же касается файла "lock" то здесь в процессе выполнения операций копирования тоже видим предупреждение "Permission denied" (см. скриншот выше), т.е. нет доступа. А доступа нет из-за недостаточных разрешений или ограниченных прав текущего пользователя.
Выполним ту же команду от суперпользователя:
$ sudo rsync -vh --progress /var/cache/apt/archives/* /media/testuser01/SecondDisk/PackagesBackup

-9

Опция "--recursive" - обработка подкаталогов

И теперь видим, что сообщения об ошибках уже не выдаются, все файлы и даже файл "lock" скопировались. А вот каталог "partial" так и нет.
И тут нет никакой ошибки, команда задана верно. Просто по умолчанию rsync копирует (пересылает) только файлы, а все каталоги пропускает. Чтобы rsync копировала и каталоги надо дать ей такое указание, т.е. добавить в команду соответствующий ключ (option). Это ключ
-r или --recursive - все подкаталоги (и подкаталоги подкаталогов т.е. рекурсивно) указанного каталога-источника.
Выполним команду с добавлением ключа -r:
$ sudo rsync -rvh --progress /var/cache/apt/archives/* /media/testuser01/SecondDisk/PackagesBackup

-10

Вот наконец-то мы видим, что все имеющиеся файлы и каталоги из источника скопированы в приёмник. Проверка через ls это подтверждает:

-11

Особенности синтаксиса - завершающий слеш.

Здесь важно отметить одну интересную особенность утилиты rsync.
А именно, теперь когда мы запускаем её с ключом -r т.е. рекурсивно, звёздочку в конце ставить не обязательно.
Вот такой синтаксис тоже будет правильным и команда отработает верно:
$ sudo rsync -rvh --progress /var/cache/apt/archives/ /media/testuser01/SecondDisk/PackagesBackup
А вот
завершающий слеш в указании пути каталога-источника ставить обязательно. Иначе команда скопирует не содержимое каталога "archives", а весь каталог целиком. Т.е. таким образом получится "вложенное дублирование".

Ну раз мы сейчас учимся, то давайте запустим и неправильный вариант (без слеша в конце) и посмотрим что получится:
$ sudo rsync -rvh /var/cache/apt/archives /media/testuser01/SecondDisk/PackagesBackup

-12

В результате получаем вот такое вложенное задваивание файлов:

-13

Вот такая, казалось бы, незначительная деталь в синтаксисе команды играет очень большое значение!
С этим разобрались. Идём дальше.

Проблема перезаписи и как RSync сравнивает файлы?
Как RSync разрешает конфликты?

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

Давайте смотреть.
Если мы ещё раз запустим на выполнение туже самую команду:
$ sudo rsync -rvh --progress /var/cache/apt/archives/* /media/testuser01/SecondDisk/PackagesBackup
То она ещё раз выполнится и ещё раз будет копировать все файлы и каталоги, а имеющиеся там файлы будут перезаписаны. Но они ведь уже есть в каталоге назначения (приёмнике), так зачем же их ещё раз копировать?
В самом деле, они ведь не были изменены - это те же самые файлы.
Кто-то может сказать: "Ну а в чём проблема? Пусть копируются и перезаписываются." Да, для нашего простого примера это не сильно критично. Но ведь в реальной ситуации могут синхронизироваться тысячи и десятки тысяч файлов, например, альбомы фотографий за несколько лет, или же файлы большого объёма 30-50ГБ или больше каждый файл, а в совокупности объёмом 5000-10000ГБ и более. А это уже серьезно. Каждый раз гонять такие объёмы данных не только не целесообразно, но и расточительно так, по сути впустую, нагружать компьютер. А если ещё при этом используются SSD-накопитель, то его вообще можно быстро убить такой вот "синхронизацией файлов".
Ну и наконец, методологически это тоже не правильно.

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

А каким образом вообще можно сравнить файлы и понять одинаковые это файлы или всё-таки разные?
На самом деле это отдельная большая тема и я не буду её здесь рассматривать полностью. Здесь я напишу только конкретные практические моменты применительно к утилите rsync.
Если говорить коротко, то сравнивать файлы можно по следующим параметрам:

  • по наименованию файлов;
  • по размеру файлов;
  • по контрольным суммам;
  • по дате создания;
  • по дате последнего доступа;
  • по дате изменения;
  • по дате модификации

Последние три параметра называются временные метки файла (Access, Modify, Change).
Ну давайте не будем долго теоритезировать, а сделаем сравнение двух каких-нибудь файлов из тех, что мы синхронизировали утилитой rsync.
Например, сравним размеры файлов в байтах в каталоге-источнике и в каталоге-приёмнике. Для этого выполним две команды:
$ du -b /var/cache/apt/archives/pcmanfm_1.2.5-3_amd64.deb
$ du -b /media/testuser01/SecondDisk/PackagesBackup/pcmanfm_1.2.5-3_amd64.deb

-14

Как мы видим, размеры файлов в точности одинаковые.
Давайте сравним контрольные суммы (checksum) файлов. Сделать это можно разными способами. Мы сделаем это самым простым и быстрым способом. А именно, воспользуемся командами md5sum, sha1sum, sha256sum:

$ md5sum /var/cache/apt/archives/pcmanfm_1.2.5-3_amd64.deb
$ md5sum /media/testuser01/SecondDisk/PackagesBackup/pcmanfm_1.2.5-3_amd64.deb
$ sha1sum /var/cache/apt/archives/pcmanfm_1.2.5-3_amd64.deb
$ sha1sum /media/testuser01/SecondDisk/PackagesBackup/pcmanfm_1.2.5-3_amd64.deb
$ sha256sum /var/cache/apt/archives/pcmanfm_1.2.5-3_amd64.deb
$ sha256sum /media/testuser01/SecondDisk/PackagesBackup/pcmanfm_1.2.5-3_amd64.deb

-15

Контрольные суммы файлов также совпадают. Т.е. у нас два полностью идентичных (по содержимому) файла: и размер файлов и контрольные суммы в точности совпадают. Остальные файлы каталога-источника и каталога-приёмника можно сравнить таким же способом и убедиться, что и остальные файлы полностью идентичны.
И тем не менее, утилита rsync почему-то "не понимает", что файлы идентичны и каждый раз их заново перезаписывает.

Теперь давайте сравним атрибуты файлов, а именно временные метки файлов (access, modify, change). В этом нам поможет команда stat.

$ stat /var/cache/apt/archives/pcmanfm_1.2.5-3_amd64.deb
$ stat /media/testuser01/SecondDisk/PackagesBackup/pcmanfm_1.2.5-3_amd64.deb

-16

И здесь мы можем увидеть очень интересную и важную для нас информацию. По умолчанию при копировании (синхронизации) утилита rsync каждый раз перезаписывает временные метки файлов. Временем последнего доступа к файлу (access), его модификации (modify) и изменения (change) становится время его копирования (текущее время в системе на момент копирования).
Опять же по умолчанию при копировании утилита rsync сравнивает файлы по временным меткам (конкретно по времени модификации), видит что файлы по этим параметрам отличаются и перезаписвает их, т.е. заново производит полное копирование всех файлов и подкаталогов.

Ну вот мы наконец-то и докопались до сути вопроса почему утилита rsync "не понимает", что файлы идентичны и каждый раз их заново перезаписывает. Осталось только найти решение, чтобы rsync понимала и не перезаписывала. А сделать это очень просто - нужно всего лишь добвать ключ -t или --times в команду. RSync с ключом -t сохраняте время модификации файла таким же, как и у исходного файла.
Давайте в этом убедимся. Выполним команду:

$ rsync -rvht --progress /var/cache/apt/archives/ /media/testuser01/SecondDisk/PackagesBackup

При этом все файлы у нас также перезапишутся.
И заново сравним атрибуты файлов командой stat:

$ stat /var/cache/apt/archives/pcmanfm_1.2.5-3_amd64.deb
$ stat /media/testuser01/SecondDisk/PackagesBackup/pcmanfm_1.2.5-3_amd64.deb

-17

И теперь мы видим, что время модификации файлов в точности совпадает.
Ну и наконец, последний шаг. Запускаем нашу команду копирования (синхронизации) ещё раз. И, о чудо, видим что никаких действий не производится, никакие файлы или каталоги никуда не копируются.
Список скопированных (пересланных) файлов пуст (sending incremental file list).

-18

Ура! Мы добились того, что хотели!
Давайте сделаем краткое резюме.
Итак, чтобы rsync "понимала", что файлы одинаковые и не перезаписывала их заново, нужно при первом запуске синхронизации исползовать ключ
-t или --times. Тогда при копировании сохраняется время модификации файлов и при повторной синхронизации rsync "увидит" что файлы одинаковые.