logo

nixscript

Keep it simple, stupid !

Ссылка на статью в формате MarkDown для Curl, кодировка RU.UTF-8

Синхронизация папок с помощью bash и rsync

Адрес статьи: nixscript.ru/sync-gechandesu

Я написал bash скрипт, позволяющий делать простую одностороннюю синхронизацию папок. Можно использовать для бэкапа файлов на съёмный носитель и вообще для синхронизации любых папок на компьютере.

Производить синхронизацию будем с помощью rsync.

Собственно, вот весь скрипт:

#!/bin/bash

syncfrom=$1
syncto=$2

if ! [ -d "$syncfrom" ]; then
    echo 'Source directory does not exist!'
elif [ "$(ls "$syncfrom" | wc -l)" -eq 0 ]; then
    echo "Source directory is empty!"
else
    while true
    do
        rsync -aP --delete "$syncfrom" "$syncto"
        sleep 2
    done
fi

Что оно делает

Скрипт в бесконечном цикле выполняет синхронизацию двух папок и имеет следующий синтаксис:

sync.sh /source/dir/ /destination/dir/

Изменения папки /source/dir/ применяются к папке /destination/dir/dir - переименование файлов, удаление, перемещение и т.п.

Как это работает

Разберём весь скрипт по порядку.

Прежде всего нас интересуют вот эти строчки:

#!/bin/bash

syncfrom="$1"
syncto="$2"

В первой строке мы указываем путь к интерпретатору. Это стандартное начало для bash скриптов.

В следующих двух строчках вводим переменные syncfrom и syncto. Это будут наши параметры, которые мы будем указывать уже при запуске скрипта.

syncfrom будет содержать путь к исходной папке, а syncto путь к папке, в которую будет производиться копирование.

Присваиваем им соотвестственно $1 и $2, что означает, что следующая команда запишет путь /source/dir/ в значение переменной syncfrom и путь /destination/dir/ в значение syncto:

sync.sh /source/dir/ /destination/dir/

Цифры 1 и 2 означают порядковый номер параметра. Если бы я указал 0, то это было бы название скрипта.

Самое интересное в скрипте это строка с вызовом rsync. Она заключена в бесконечный цикл, чтобы постоянно мониторить нашу исходную папку и при необходимости производить синхронизацию.

while true
    do
        rsync -aP --delete "$syncfrom" "$syncto"
        sleep 2
    done

Рассмотрим ближе строку

rsync -aP --delete "$syncfrom" "$syncto"

Здесь параметр -aP означает, что rsync будет действовать рекурсивно и выводить лог синхронизации в терминал.

--delete разрешает удаление, если файлы/папки были удалены из исходной папки. Если вам это не нужно, просто не указывайте этот параметр.

$syncfrom и $syncto это, как уже выше было сказано, пути к папкам.

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

rsync -aP --delete --exclude=desktop.ini --exclude=*.tmp "$syncfrom" "$syncto"

В этом примере исключаются файлы desktop.ini и все файлы с расширением .tmp.

В том же цикле, что и rsync вызывается команда sleep со значением 2. Это пауза в две секунды. Она тут ради экономии ресурсов компьютера, чтобы не проводить синхронизацию много тысяч раз в секунду. Раз в две секунды для наших целей вполне достаточно.

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

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

Для того, чтобы синхронизация не началась с пустой или несуществующей папкой нужно написать обработчики. За это отвечают строки:

if ! [ -d "$syncfrom" ]; then
    echo 'Source directory does not exist!'
elif [ $(ls "$syncfrom" | wc -l) -eq 0 ]; then
    echo "Source directory is empty!"
else
...

Строка c if проверяет существует ли указанная исходная папка и возвращает сообщение об ошибке, если результат ложь.

elif проверяет не пустая ли папка и сообщает, если это так.

Если оба условия выполнились, то синхронизация начинается.

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

Как использовать

Скачать скрипт: https://github.com/gechandesu/sync

Положите файл sync.sh в любое удобное место и дайте ему права на выполнение:

chmod +х sync.sh

Далее выполните скрипт с указанием параметров:

sync.sh /source/dir/ /destination/dir/

где /source/dir/ это путь к исходной папке, а /destination/dir/ путь к папке назначения.

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

Автор: gechandesu 10.05.2019


Статья написана в формате MarkDown и сконвертирована в HTML с помощью скрипта Parsedown.

Вверх 🡑