ZLU (ZeroLab Unisync): remote & local automated backup script

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

Итак, ZLU (ZeroLab Unisync):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#!/bin/sh

# --------------------------------------------
# ZLU (ZeroLab Unisync):
# remote & local automated backup script
# Written by ZeroChaos
# Version 1.5, 2012-11-20
# Site: http://zerolab.net/
# --------------------------------------------
# NOTE: Exclude spaces in the variable FOLDER!
# --------------------------------------------

# -------------------------------------------- begin of [Configurable settings]
# Use SSH for remote sync
export RSYNC_RSH="ssh -c arcfour -o Compression=no -x"

# Snapshot directory
SDIR="snapshot"
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]
# 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:

1
2
3
/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][snapshot_trigger][snapshot_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:

1
2
3
4
5
6
temp/summ/checks/*
temp/sess/*
temp/tmp/*
template_cache/*
cache/*
logs/*

Напомню про snapshot’ы. Скрипт позволяет опционально делать snapshot’ы, содержащие измененные, либо удаленные файлы. Тем самым, появляется возможность откатиться на старые версии файлов, случайно удаленных, к примеру, либо ошибочно измененных. При этом сохраняется полная изначальная структура каталогов, что позволяет легко найти требуемый файл. Snapshot’ы хранятся в каталогах со следующей маской в имени: ‘год-месяц-день.XXчXXм’. Есть возможность авторотации snapshot’ов, выставляете количество дней, отвечающее вашим требованиям, и имеете возможность спокойно восстановить рассортированные данные за эти дни.

Как и ранее, имеется возможность генерации ключа для авторизации по SSH, а так же его копирования на backup-сервер. Для авторизации с backup-сервером воспользуемся беспарольным вариантом, т.е. авторизацией по ключу. Для этого сгенерируем пару public/private rsa key. Выполним скрипт с ключом -g:

1
./backup.sh -g

Отвечаем на заданные вопросы и переходим к копированию открытого ключа на удаленный сервер. Для этого выполним скрипт с ключом -c:

1
./backup.sh -c

Будет выведен список удаленных хостов. Выбираем.

Вводим пароль пользователя, под которым будет происходить дальнейшая авторизация по ключу во время резервного копирования. Две команды выше можно объединить в одну, тогда операции будут выполнены последовательно:

1
./backup.sh -gc

Остается добавить скрипт в cron:

1
2
#minute hour    mday    month   wday    command
0       1       *       *       *       bash /scripts/backup.sh

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

Категория: *nix, Programming

Теги: , , , , ,

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

XHTML: Вы можете использовать следующие теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>
Аватары обслуживаются системой Gravatar. При публикации сообщения, Вы можете указать свой e-mail в этой системе.

Twitter

MSI Lab Twitter
Яндекс.Деньги:

VISA/MasterCard:

PayPal:
PayPal USD
PayPal RUB
WMZ WMZ: Z375880088307
WMR WMR: R883546545943
YAD YAD: 4100170884493

Donate - лучшее спасибо автору
Количество благодарностей: 30

Разделы