вторник, 18 марта 2014 г.

Rsync - синхронизация данных между устройствами

~/scripts/sync.html

Если вы пользуетесь более, чем одним компьютером, то, скорее всего, вам приходилось сталкиваться с тем, что данные, с которыми вы работаете, должны быть на всех компьютерах, при чём изменения, внесённые на одном компьютере, должны быть актуальны и на других. Для этих целей можно использовать флешку, и работать с ней напрямую, или пользоваться облачным сервисом для оптимизации, наподобие Dropbox или Яндекс-диск. При использовании флешки необходимо резервное копирование данных, так как флешка - устройство ненадёжное, да и можно просто её потерять. Использование облачных сервисов требует постоянного подключения к интернету, что может оказаться не всегда возможным. Предлагаю способ прямой (возможна косвенная) синхронизации между компьютерами с использованием rsync, которую использую я сам.

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

Преимущество rsync состоит в том, что он не копирует данные целиком, а ищет различия между каталогами и даже содержимым файлов, и пересылает только их. Rsync поддерживает сжатие, может работать через собственный протокол, через ssh или же напрямую через файловую систему.

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

Файл sync

 1 #!/bin/bash
 2 host="vladimir-laptop"
 3 if [ "$PARAMS" = "" ]
 4 then
 5     PARAMS="-aHvuzn --progress --delete-after"
 6 fi
 7 if [[ $1 == "-h" ]]
 8 then
 9     echo "Синхронизация файлов между компом и ноутбуком"
10     echo "Все каталоги и файлы читаются из файла synclist.txt"
11     exit
12 fi
13 if [ -z $2 ]
14 then
15     path=$host::vladimir
16 else
17     path=$(echo "$2" | sed 's/\/*$//')
18 fi
19 if [[ $1 == "to" ]]
20 then
21     sourcepath=$HOME
22     destpath=$path
23 else
24     if [[ $1 == "from" ]]
25     then
26         sourcepath=$path
27         destpath=$HOME
28     else
29         echo "unknown option: $1"
30         exit 1
31     fi
32 fi
33 echo
34 echo "Start syncronization..."
35 echo "rsync $PARAMS --files-from=synclist.txt -r $sourcepath $destpath"
36 rsync $PARAMS --files-from=synclist.txt -r "$sourcepath" "$destpath" || exit 1

Скрипт используется с двумя параметрами командной строки. Первый параметр - "to" или "from", зависит от направления синхронизации, второй параметр - это адрес устройства, если он не задан, по умолчанию в моём случае используется vladimir-laptop::vladimir, следует заменить на свой случай, т.е. задать переменную host и дальнейший путь синхронизации.

В этом примере путь указан через два двоеточие, это означает, что будет использоваться протокол rsync. Если использовать одно двоеточие, то будет использоваться ssh, если просто указать путь к папке, то, соответственно, будет прямая синхронизация внутри одного устройства (например, при синхронизации посредством флешки).

Для текущего компьютера путь по умолчанию задаётся $HOME, т.е. домашняя директория пользователя, запускающего скрипт.

Также для управления скриптом используется переменная окружения PARAMS, которая, если не задать её в оболочке, принимает значение по умолчанию, заданное в скрипте. Опишу подробно параметры:

  • -a - сохранять атрибуты файла: время изменения/создания, владельца, группу и прочее;
  • -v - печатать в стандартный вывод о производимых операциях;
  • -z - использовать сжатие;
  • -H - создавать на приёмнике жёсткие ссылки, как на источнике;
  • -u - заменять файлы только если на источнике они новее, чем на приёмнике;
  • -n - не производить реальных действий, только имитировать;
  • --delete-after - удалять файлы, которых не существует на источнике, при чём только после того, как будут скопированы и обновлены существующие файлы.

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

Поэтому я использую ещё один вспомогательный скрипт, который выполняет синхронизацию после того, как я убедился, что параметры введены верно, и данные не будут потеряны:

Файл realsync

1 #!/bin/bash
2 export PARAMS="-avuHz --progress --delete"
3 ./sync $@

Он просто задаёт параметры синхронизации:

  • --progress - показывать прогресс копирования отдельных файлов (удобно, если файлы имеют большой размер и требуется время для их копирования);
  • --delete - удалить файлы, которых не существует на источнике (просто удаляет в процессе синхронизации, а не в конце её).

Таким образом процесс синхронизации выполняется вызовом сначала ./sync, потом ./realsync. Можно из первого скрипта удалить параметр -n, но тогда можно случайно удалить нужные данные.

Помимо этого скрипт использует файл synclist.txt, содержащий пути к синхронизируемым файлам и папкам относительно домашнего каталога. Должен находится в каталоге, из которого вызывается скрипт. Например, мой файл выглядит так:

scripts/
Документы/
Projects/
vladimir.kdb
.local/share/gtg/
.local/share/gnote/
vimwiki/

Настройка rsync

Если вы собираетесь синхронизировать данные посредством флешки, то ничего настраивать не нужно, достаточно установить rsync. Вот только придётся отформатировать флешку в файловую систему, поддерживающую аттрибуты Posix, т.е. FAT и NTFS не подойдут.

Для синхронизации через ssh помимо установки самого rsync необходимо наличие ssh-сервера на удалённом компьютере. Также, чтобы не вводить каждый раз пароль, можно настроить ключи ssh.

Для синхронизации через протокол rsync, т.е. как в приведённом примере, нужно настроить демон rsync, для этого нужно в файл /etc/rsyncd.conf вписать что-то вроде:

[name]
    path = /home/user
    comment = Rsync syncronization
    hosts allow = 10.42.0.0/16

Здесь name - произвольное имя, оно будет использоваться после двойного двоеточия, comment - вообще произвольный коментарий, hosts allow - адреса, с которых разрешён доступ, можно опустить, тогда доступ будет разрешён с любого адреса.

Далее следует перезапустить демон:

#service rsyncd restart

Подробнее можно прочитать в man rsyncd.conf и man rsync.

Комментариев нет:

Отправить комментарий