ZLU (ZeroLab Unisync): remote & local automated backup script
Появилось немного времени и я решил переписать скрипт для автоматизации задачи бэкапа данных. Раньше скрипт неизбежно приходилось дублировать, если каталоги назначения различались, для локального же бэкапа приходилось немного модифицировать сценарий. Теперь этого делать не нужно, один универсальный скрипт способен проделать несложные операции за вас, нужно лишь задать необходимые параметры в файле настроек.
Итак, ZLU (ZeroLab Unisync):
#!/bin/bash # -------------------------------------------- # ZLU (ZeroLab Unisync): # remote & local automated backup script # Written by ZeroChaos # Version 1.5, 2012-11-20 # Site: https://zerolab.net/ # -------------------------------------------- # NOTE: Exclude spaces in the variable FOLDER! # -------------------------------------------- # -------------------------------------------- begin of [Configurable settings] # Use SSH for remote sync export RSYNC_RSH="ssh -c [email protected] -o Compression=no -x" #export RSYNC_RSH="ssh -c [email protected] -o Compression=no -x -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" # Snapshot directory SDIR="versioning" SNAPSHOT_dir="$SDIR/`date +'%Y-%m-%d.%Hh%Mm'`" # Take the list from the same folder where the script is called DIR=$(dirname "$0") LISTFOLDERS="$DIR/backup.txt" EXCLUSIONSDIR="$DIR" # -------------------------------------------- end of [Configurable settings] # -------------------------------------------- begin of [Do not touch this section] # Backup DB #$DIR/backup-db.sh # If no arguments if [ $# = 0 ]; then SNAPSHOT_GLOBAL="disable" i=0 while read LINE; do if [ -n "$LINE" ]; then IFS=";" set -- $LINE FOLDER="$1" DEST_point="$2" LISTEXCLUSIONS="$EXCLUSIONSDIR/$3" SNAPSHOT="$4" SDAYS="$5" REMOTEHOST="${6}@${7}" FOLDERNAME="`echo "$FOLDER" | awk -F/ '{ print $NF }'`" # Options for rsync + array of commands to autorotation if [ $SNAPSHOT = "enable" ]; then SNAPSHOT_GLOBAL="enable" if [ "$6" != "" ] && [ "$7" != "" ]; then OPTIONS="-Sazq --bwlimit=3840 --delete --exclude-from=$LISTEXCLUSIONS --backup --backup-dir=${DEST_point}${SNAPSHOT_dir}/$FOLDERNAME" SAR[$i]="ssh $REMOTEHOST \"find ${DEST_point}${SDIR}/ -type d -mtime +$SDAYS -exec rm -r {} \;\" >/dev/null 2>&1" i=$(($i+1)) else OPTIONS="-Saq --delete --exclude-from=$LISTEXCLUSIONS --backup --backup-dir=${DEST_point}${SNAPSHOT_dir}/$FOLDERNAME" SAR[$i]="find \"${DEST_point}${SDIR}/\" -type d -mtime +$SDAYS -exec rm -r {} \; >/dev/null 2>&1" i=$(($i+1)) fi else if [ "$6" != "" ] && [ "$7" != "" ]; then OPTIONS="-Sazq --bwlimit=3840 --delete --exclude-from=$LISTEXCLUSIONS" else OPTIONS="-Saq --delete --exclude-from=$LISTEXCLUSIONS" fi fi # Sync if [ "$6" != "" ] && [ "$7" != "" ]; then eval rsync $OPTIONS "${FOLDER}/" $REMOTEHOST:"${DEST_point}${FOLDERNAME}/" else eval rsync $OPTIONS "${FOLDER}/" "${DEST_point}${FOLDERNAME}/" fi fi done < $LISTFOLDERS # Snapshot auto-rotate if [ $SNAPSHOT_GLOBAL = "enable" ]; then for ((a=0; a<${#SAR[*]}; a++)); do eval "${SAR[$a]}" done fi fi # Generate public/private rsa key pair ssh_keygen() { ssh-keygen -t rsa -b 4096 } # Copy your public key on a remote machine ssh_copy_id() { # Function for remote host choice PS3='Select the remote host: ' rhchoice() { eval set $RHARR select RH; { REMOTEHOST=$RH break } } # Read the list of remote hosts while read LINE; do IFS=";" set -- $LINE if [ "$6" != "" ] && [ "$7" != "" ]; then RH="${6}@${7}" RHARR="$RHARR $RH" fi done < $LISTFOLDERS # Remote host choice if [ "$RHARR" != "" ]; then rhchoice $RHARR else echo "No remote hosts, please configure the settings file: $LISTFOLDERS" fi ID_FILE="${HOME}/.ssh/id_rsa.pub" if [ x$SSH_AUTH_SOCK != x ] && ssh-add -L >/dev/null 2>&1; then GET_ID="$GET_ID ssh-add -L" fi if [ -z "`eval $GET_ID`" ] && [ -r "${ID_FILE}" ]; then GET_ID="cat ${ID_FILE}" fi if [ -z "`eval $GET_ID`" ]; then echo "$0: ERROR: No identities found" >&2 exit 1 fi if [ "$RHARR" != "" ]; then { eval "$GET_ID" ; } | ssh ${REMOTEHOST%:} "umask 077; test -d .ssh || mkdir .ssh ; cat >> .ssh/authorized_keys" || exit 1 fi } ME=$(basename "$0") print_help() { echo echo "Usage: $ME [OPTION...]" echo echo "Options:" echo " -g Generate public/private rsa key pair:" echo " ssh-keygen -t rsa -b 4096" echo " -c Copy your public key on a remote machine:" echo " ssh-copy-id user@host" echo " -h Help." echo echo "Example: $ME -gc" echo "Use both options, generate & copy." echo } while getopts ":gch" opt; do case $opt in g) ssh_keygen; ;; c) ssh_copy_id; ;; h) print_help; ;; *) echo "Wrong option"; echo "For help, use: $ME -h"; exit 1 ;; esac done # -------------------------------------------- end of [Do not touch this section]
Файл настроек принял следующий вид:
backup.txt:
/home/zerochaos/www/zerolab.net;/home/zerochaos/www/;exclude.txt;enable;15;zerochaos;backup.zerolab.net /Users/zerochaos/data;/Volumes/BACKUP/;exclude.txt;disable;30 # [source_folder][destination_folder][exclusions_list]# [source_folder][destination_folder][exclusions_list][versioning_trigger][versioning_days][user][host] -- [do not delete this string]
Как видите, в одном файле настроек можно задать параметры как для удаленной, так и для локальной синхронизации. Разберем параметры каждого столбца, что за что отвечает:
1) [source_folder]: каталог, резервную копию которого мы делаем
2) [destination_folder]: каталог, куда мы сохраняем резервную копию
3) [exclusions_list]: список с масками исключений (формат смотрите в мане rsync)
4) [snapshot_trigger]: включаем или выключаем создание снапшотов
5) [snapshot_days]: указываем количество дней для авторотации снапшотов
6) [user]: имя пользователя удаленного хоста, на который производится резевное копирование
7) [host]: имя или IP этого хоста
Разделитель: «;»
6 и 7 параметры следует указывать только в том случае, если мы производим резервное копирование на удаленную машину. Заполняем список заданий для удаленного и локального бэкапа в одном файле, скрипт выполнит цикл резервного копирования. Каждое задание на новой строке, последнюю строку с комментариями не удаляем.
Пример exclude.txt:
temp/summ/checks/* temp/sess/* temp/tmp/* template_cache/* cache/* logs/*
Напомню про версионирование. Скрипт позволяет опционально вести версионирование, которое содержит измененные, либо удаленные файлы. Тем самым, появляется возможность откатиться на старые версии файлов, случайно удаленных, к примеру, либо ошибочно измененных. При этом сохраняется полная изначальная структура каталогов, что позволяет легко найти требуемый файл. Версии хранятся в каталогах со следующей маской в имени: ‘год-месяц-день.XXчXXм’. Есть возможность авторотации, выставляете количество дней, отвечающее вашим требованиям, и имеете возможность спокойно восстановить рассортированные данные за эти дни.
Как и ранее, имеется возможность генерации ключа для авторизации по SSH, а так же его копирования на backup-сервер. Для авторизации с backup-сервером воспользуемся беспарольным вариантом, т.е. авторизацией по ключу. Для этого сгенерируем пару public/private rsa key. Выполним скрипт с ключом -g:
./backup.sh -g
Отвечаем на заданные вопросы и переходим к копированию открытого ключа на удаленный сервер. Для этого выполним скрипт с ключом -c:
./backup.sh -c
Будет выведен список удаленных хостов. Выбираем.
Вводим пароль пользователя, под которым будет происходить дальнейшая авторизация по ключу во время резервного копирования. Две команды выше можно объединить в одну, тогда операции будут выполнены последовательно:
./backup.sh -gc
Остается добавить скрипт в cron:
#minute hour mday month wday command 0 1 * * * bash /scripts/backup.sh
Скрипт будет работать в любой операционной системе, где возможна установка rsync client и имеется командный интерпретатор.