Скрипт инкрементного резервного копирования.

Опубликовано beregov.a.e - чт, 11/09/2017 - 13:11

Про резервное копирование в интернетах много всего. Предлагаю вашему вниманию моё решение.

Немного истории данного произведения. Однажды мне потребовалось настроить резервное копирование на centos тогда ещё 6.5 или 6.4 Там располагался файловый сервер на samba.  Из-за чего начал изучать данный вопрос с помощью интернетов. Поисковик выдавал много всего. Из всего того что на тот момент я тогда нашёл, меня ничего не устроило. Хотелось простого и к тому же компактного решения. Тогда я ещё не умел программировать на sh/bash. И вот начитавшись про резервное копирование и насмотревший разных скриптов, я решил или мне помог в напутствие мой тогда работодатель. Написать самому своё решение. На тот момент я в какой то статье читал что хорошо бы было проверять изменение файла не по времени, а по контрольной сумме. И то что инкрементное резервное копирование занимает меньше места.    

#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
#Переменные времени
TIME_now=`date +"%F"` # текущая дата
TIME_now_dir=`date '+%Y/%m/'`
TIME_now_OLD=`date --date='1 day ago' +"%F"` # вчерашняя дата для файла
TIME_yesterday=`date --date='1 day ago' '+%Y/%m/'` # вчерашняя дата для директории
TIME_BACKUP_FULL=`date +"%Y-%m-01"` # Последний полный архив системы каждое первое число
TIME_BACKUP_FULL_sunday=`date --date='sunday' '+%F'` # воскресенье инкрементный архив относительно полного архива
TIME_BACKUP_FILE_OLD=`date  +"%Y-%m-01"`
TIME_BACKUP_DIR_FULL=`date  '+%Y/%m/'` #  текущего месяца
# Переменные дирикторий
BACKUP_DIR=/home/backup/system/ # Куда складывать бэкапы
DATA_DIR=`date +"%Y/%m/"` # Дата для создания папки для архива
DIR_PATCH=$BACKUP_DIR$DATA_DIR  # Куда будет сохранён архив
DIR_PATCH_OLD=$BACKUP_DIR$TIME_yesterday # где хранится прошлый бэкап
DIR_PATCH_SITES=$DIR_PATCH/sites # Архивы сайтов]
# Переменные файлов архивов
FILE_BACKUP=$DIR_PATCH/$TIME_now.tar.xz # полный путь к файлу бэкапа который будет создаваться
FILE_BACKUP_OLD=$DIR_PATCH_OLD$TIME_now_OLD.sum # полный путь к информационному файлу бэкапа, вчерашняя архивация
FILE_BACKUP_FULL=$DIR_PATCH$TIME_BACKUP_FULL.sum # путь к информационному файлу бэкапа текущего месяца. Чтоб проверить есть ли он или нет.
# Переменные файлов с информацией
BACKUP_NOW_LIST_TMP=$DIR_PATCH$TIME_now.tmp  #Результаты сканирования, которое сейчас запустим.
BACKUP_NOW_OLD=$DIR_PATCH #Результаты сканирования. Прошлого бэкапа, для инкрементального бэкапа.
BACKUP_NOW_LIST=$DIR_PATCH$TIME_now.sum # Результаты сканирования в месте с контрольной суммой и экранированными строками.
BACKUP_NOW_LIST_GOOD=$DIR_PATCH$TIME_now # Результаты сканирования с экранированными строками
BACKUP_NOW_LIST_TMP_SITES=$DIR_PATCH$TIME_now-SITES.tmp
# Переменные для хранения файлов бэкапов
days=7
weeks=4
mouths=3
parm_day=Sunday

mkdir -p $DIR_PATCH # созаём директорию, где будут хранится архив и список файлов.
echo $TIME_now >> /var/log/backup.log
# rm -f $BACKUP_NOW_LIST_TMP
# Какие директории будем архивировать. Тут можно добавить по аналогии ещё директории.
find /samba/Documents -type f >> $BACKUP_NOW_LIST_TMP
find /samba/WWW -type f >> $BACKUP_NOW_LIST_TMP

# что игнорировать из поиска
#grep -v '\(error\|added\)'
IGNOR='sess*'

# Экранируем строки в двойные кавычки
sed 's/^/"/;s/$/"/' $BACKUP_NOW_LIST_TMP | grep -v $IGNOR > $BACKUP_NOW_LIST_GOOD

# Подчитываем хэш сумму у найденных файлах. И экранируем в двойные ковычки строку.
while read line; do echo "$line" | xargs md5sum ; done < $BACKUP_NOW_LIST_GOOD | sed 's|[/*]|"/|;s|$|"|' > $BACKUP_NOW_LIST

# Описание функций резерного копирования
BACKUP_FULL ()# функция полнго резервного копирования
{
while read line; do echo "$line" | sed -e 's/^[^ ]*\(.*\)$/\1/;s/^[ \t]*//' ; done < $BACKUP_NOW_LIST | xargs tar -cf - | xz -9 -c > $FILE_BACKUP # считываем содержимое из файла строки для архивации
rm -f $BACKUP_NOW_LIST_TMP
rm -r $BACKUP_NOW_LIST_GOOD
}
BACKUP_INCREMENT_SUNDAY ()# функция еженедельного инкрементного копирования относительно текущего месяца
{
#Если в директории имеются файл. Ключ -f проверяет наличие файлов.
if [ -f $FILE_BACKUP_FULL ];
        then # Если существует то
                diff -d $FILE_BACKUP_FULL $BACKUP_NOW_LIST | grep '>' | awk '{print $2 "\t" $3}' > $BACKUP_NOW_LIST.diff # сравниваем списки файлов. Полного бэкапа и воскресного который будет создан.
                while read line; do echo $line | sed -e 's/^[^ ]*\(.*\)$/\1/;s/^[ \t]*//' ; done < $BACKUP_NOW_LIST.diff  | xargs tar -cf - | xz -9 -c > $FILE_BACKUP
                rm -f $BACKUP_NOW_LIST_TMP
                rm -r $BACKUP_NOW_LIST_GOOD
        else
                BACKUP_FULL
fi
}
BACKUP_INCREMENT_DAY ()# функция ежидневного резегвного копирования
{
if [ -f $FILE_BACKUP_OLD ]; # проверяем
        then
                diff -d $FILE_BACKUP_OLD $BACKUP_NOW_LIST | grep '>' | awk '{print $2 "\t" $3}' > $BACKUP_NOW_LIST.diff
                while read line; do echo $line | sed -e 's/^[^ ]*\(.*\)$/\1/;s/^[ \t]*//' ; done < $BACKUP_NOW_LIST.diff | xargs tar -cf - | xz -9 -c > $FILE_BACKUP
                rm -f $BACKUP_NOW_LIST_TMP
                rm -r $BACKUP_NOW_LIST_GOOD
        else
                BACKUP_FULL

cp $BACKUP_NOW_LIST  $FILE_BACKUP_FULL


fi
};
# функция разервнрго копирования баз данных для mysql
BACKUP_FULL_DATABASES ()
{
mkdir -p $BACKUP_DIR$DATA_DIR/databases
$BACKUP_DIR$DATA_DIR/databases
for i in `mysql -uroot -pPASSWORD -e'show databases;' | grep -v '\(performance_schema\|information_schema\|Database\)'`; do mysqldump -u root -pPASSWORD $i | xz -9 `date +%Y-%m-%d`-$i;done
}


# Сравниваем дату.
if [ "$TIME_now" = "$TIME_BACKUP_FULL" ] # Если сегодня первое число месяца то выполняем полное архивирование
        then
            BACKUP_FULL

        elif [ "$TIME_now" = "$TIME_BACKUP_FULL_sunday" ] # Если сегодня воскресенье то выполняем инкрементное архивирование относительно полного
        then
            BACKUP_INCREMENT_SUNDAY

        else # Иначе выполняем инкрементное архивирование относительно прошедшого дня.
            BACKUP_INCREMENT_DAY

fi

DATA_days () {
i=1
while [ "${i}" -le "${1}" ]
do
date --date="${i} ${2} ago ${3}" +"%F"
i=`expr $i + 1`
done
}

rm_days=`DATA_days ${days} day`
rm_weeks=`DATA_days ${weeks} week ${parm_day}`
rm_mouths=`DATA_days ${mouths} month`


rm=`echo $rm_days $rm_weeks $rm_mouths | sed 's![ \t]!\\\|!g'`
find /home/backup/ -type f | grep -v $rm | xargs /bin/rm -f

Теги