Скрипт резервного копирования файлов с удаленного сервера.
PULL метод, в своей работе использует Rsync и транспорт ssh.
Копии хранятся в открытом виде, не архивируются.
Поддержка нескольких каталогов-источников.
Поддерживает исключения, явные и исключения по шаблону, подробно откоментировал в листинге
Скрипт ведет логи, искать в /var/logs/rsync/%имя_скрипта%
В логах генерирует фал - статус, на его основе можно подключить мониториг бэкапа в zabbix.
Сам скрипт хорошо комментирован, в статье ничего писать не буду, все есть в листинге.
Подготовка
Скрипт для загрузки файлов использует ssh транспорт, значит должна быть возможность подключиться по ssh на тот ПК с которого снимаем бэкапы. Плюс нужно настроить прозрачную авторизацию ssh по ключам, чтобы не оставлять пароли в скриптах.
Кстати, этим же скриптом можно пользоваться и локально, т.е. просто по ssh подключаемся сами к себе (HOST=127.0.0.1). Конечно выглядит как костыль, но мне лень писать отдельный скрипт для локального использования, так сказать унификация в действии.
Если бэкап нужно снять с Windows, то просто дополнительно устанавливаем CygWin и настраиваем ssh сервер по этой статье.
Требование для ПК на котором запускаем скрипт - должен быть установлен rsync.
Этот же скрипт можно запускать и на Windows машинах в linux среде, для этого устанавливаем CygWin.
Запустить sh-скрипт в Windows можно любым из двух способов:
Просто переходим в каталог, где лежат копии и забираем оттуда файлы за нужную дату.
Инкременты в каталогах c префиксом olds.
Листинг
#!/bin/bash
# Пользователь под которым мы лезем на удаленную машину по ssh. Предварительно настрой авторизацию по ключу.
# команда ssh-keygen из под пользователя, который будет запускать скрипт
# затем команда ssh-copy-id user@remotehost
USER=km
# Адрес удаленной машины откуда забираем файлы
HOST=192.168.110.6
# Порт подключения к ssh, 22 по умолчанию
PORT=22
# Массив каталогов на удаленной машине для бэкапа, регистр символов важен!
# Тут 2 очень интересных момента. Используется шаблон с подстановочным знаком - /cygdrive/c/Users/*/Desktop
# Этой одной строчкой скопируются подкаталоги Desktop у ВСЕХ пользователей сколько бы их ни было.
# И второй момент станет понятен, если почитать что находится в списке исключений. Там написано '/cygdrive/c/Users'
# Получается конфликт - вроде папку Users скрипт скопировать не должен вообще, но у нас же явно задано условие /cygdrive/c/Users/*/Desktop
# В данном случае ЯВНО заданная папка будет скопирована, а ВСЕ ОСТАЛЬНОЕ из каталога Users будет проигнорировано
SOURCE=(
"/cygdrive/c/Users/*/Desktop"
"/cygdrive/c/Users/*/Documents"
"/cygdrive/c/Users/*/Downloads"
"/cygdrive/c/Users/*/AppData/Roaming/1C/1CEStart"
"/cygdrive/c"
"/cygdrive/d"
"/cygdrive/g"
)
# Куда складывать архивы
DEST=/var/hdd4tb/TS1/manual/files-copied-by-script
# Лист исключений. Обращаю внимание, что *.cdx и *.CDX с точки зрения linux это разные исключения.
# НЕЛЬЗЯ массив оставлять пустым, обязательно нужно какое то значение, иначе скрипт не работает.
# Сейчас настроен набор исключений по умолчанию для Windows и файловых 1с
EXCL=(
'desktop.ini'
'thumbs.db'
'pagefile.sys'
'$Recycle.Bin'
'$RECYCLE.BIN'
'hiberfil.sys'
'bootmgr'
'BOOTSECT.BAK'
'System Volume Information'
'Documents and Settings'
'/cygdrive/c/PerfLogs'
'/cygdrive/c/Boot'
'/cygdrive/c/Program Files'
'/cygdrive/c/Program Files (x86)'
'/cygdrive/c/ProgramData'
'/cygdrive/c/Recovery'
'/cygdrive/c/Users'
'/cygdrive/c/Windows'
'*.cdx'
'*.CDX'
'1CHelpIndex'
'1Cv8FTxt'
'1Cv8Log'
'1Cv8Temp'
'1Cv8JobScheduler'
)
# Сколько дней хранить архивы
KEEPDAYS=22
### Дальнейшие параметры не надо менять без острой необходимости.
### они нужны для тонкой настройки в исключительных случаях
# Определяем дату
DATE=`date +%Y-%m-%d_%H-%M`
# Лог вывода rsync
RSLOG="/var/log/rsync/`basename "$0"`"
# Имя файла с исключениями. Не надо менять
EXCLFILENAME=`pwd`/`basename "$0"`-$DATE.excl
# Опции rsync, удобно менять тут, а не в экзекуции.
# опция --dry-run в самом начале - сухой прогон, тест, без реального копирования файлов
# опция --max-size=150mb не копированть файлы больше указанного размера
# опция --relative создает полный путь каталогов от корня, что удобно при бэкапе с использованием маски.
# например удобно бэкапить рабочие столы ВСЕХ пользоватиелей одной строкой "/cygdrive/c/Users/*/Desktop"
# Сейчас стоит набор опций по умолчанию, подходящий практически под все задачи
OPTS="--relative --exclude-from=$EXCLFILENAME --backup --backup-dir=$DEST/olds-$DATE --delete-during --force -avvzhe"
# Подготавливаемся к работе, создаем необходимые каталоги
mkdir -p $RSLOG
mkdir -p $DEST
# Создаем файл с исключениями, подправим системную переменную IFS, чтобы она счиатала разделителем значений массива только знак перевода строки
# по умолчанию в ней еще знак табуляции и пробел.
# После генерации файла с исключением вернем переменную IFS в прежнее значение
IFSHOLD=$IFS
IFS=$'\n'
for exclusion in ${EXCL[@]}; do
echo $exclusion>>$EXCLFILENAME
done
IFS=$IFSHOLD
# Обрабатываем массив с перечнем источников.
# Второй строкой в цикле жмем логи rsync
for folder in ${SOURCE[@]}; do
rsync --log-file=$RSLOG/$DATE-rsync-backup-$(basename $folder).log $OPTS "ssh -p $PORT" $USER@$HOST:$folder $DEST 2> $RSLOG/rsync-status-$(basename $folder).log
/usr/bin/gzip -f $RSLOG/$DATE-rsync-backup-$(basename $folder).log
# Проверка создания бэкапа. Если все нормально rsync не выводит ничего в STDERROR и лог status выглядит как пустой файлы
# Если файл пуст - добавляем в него метку ОК. Если файл не пуст - дописываем ему в конец ERROR
# Лог status затирается при каждом бэкапе и содержит статус только последней операции
if [ ! -s $RSLOG/rsync-status-$(basename $folder).log ]
then
echo "$DATE $DEST/$(basename $folder) - OK" >> $RSLOG/rsync-status-$(basename $folder).log
else
echo "$DATE $DEST/$(basename $folder) - ERROR" >> $RSLOG/rsync-status-$(basename $folder).log
fi
# Чистим лог архивирования конкретной папки
/usr/bin/find $RSLOG/*rsync-backup-$(basename $folder).* -type f -mtime +$KEEPDAYS -print -exec rm -rf {} \;
done
# Удаляем OLDS старше KEEPDAYS дней
/usr/bin/find $DEST/ -type d -name 'olds-*' -mtime +$KEEPDAYS -print -exec rm -rf {} \;
# Удаляем промежуточный файлик с исключениями
rm -f $EXCLFILENAME