Скрипт инкрементального и полного бэкапов

Rate this post

У меня недавно на работе была задача, придумать бэкап для файлового сервера с документами, фотками, презентациями и прочей фигней. Система на которой расположен файловый сервер, не обычный Linux, а точнее вообще не Linux, это FreeNas. Это очень переработанная и урезанная версия Фряхи подогнанная для одной простой цели, быстро и удобно разворачивать Storage-хранилища, все это дело работает на файловой системе ZFS. Кстати не в тему, но все же, FreeNas очень хорош, особенно когда нужно развернуть сетевое хранилище в короткие сроки, все плюшки из коробки SSH, NFS, SAMBA, LDAP + Web-интерфейс и удобная командная строка как всегда под рукой. Так вот, вернемся к нашему бэкапу. Я сначала начал смотреть в сторону готовых решений, типа Bacula или Obnam, но их не так просто поставить на сильно урезанном FreeNas, к тому же времени просто не было на это.

В связи с этим, я начал искать готовые скрипты, ну и тут все не то (напоминаю это связано с ограничениям самой системы FreeNas). Короче я на все плюнул, и закатал свой скрипт. Так как скрипт должен уметь делать инкрементальный бэкап, я смотрел в сторону tar, rdiff-backup и rsync. В итоге остановился на rsync.

Теперь к делу, задача:

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

Решение, сначала приведу пример папок необходимых для хранения копий:

[alexander@files /mnt/files2]$ ls -la
total 16
drwxrwxrwx+ 6 root  wheel    11 Jun 14 14:59 .
drwxr-xr-x  5 root  wheel   512 Jun 21 17:16 ..
drwxr-xr-x  2 root  wheel     3 Jun 27 15:23 FullMonth
drwxr-xr-x  2 root  wheel     2 Jun 27 12:04 FullWeelky
drwxr-xr-x  2 root  wheel     2 Jun 27 12:04 IncrementBackup
-rwxrwxrwx+ 1 root  wheel  3229 Jun 27 12:09 backRsync.sh
-rw-r--r--  1 root  wheel    17 Jun 27 12:04 backup_exclude.lst
-rw-r--r--  1 root  wheel    11 Jun 27 12:06 backup_include.lst
-rw-r--r--  1 root  wheel    11 Jun 13 16:01 backup_src.lst
drwxr-xr-x  2 root  wheel     3 Jun 27 15:23 temp

Думаю тут все понятно, ибо имена я старался давать читабельные, все эти папки живут на том же диске что и бэкапы /mnt/files

Код скрипта

[alexander@files /mnt/files2]$ vi backRsync.sh
#!/bin/sh
# cron: 0 3 * * * root /root/adm/backup.sh
# Script for Incremential and Full backup of files
 
# Where to put backup files
BACKUP_DIR=/mnt/files2/IncrementBackup
WEEKLY_BACKUP=/mnt/files2/FullWeelky
MONTH_BACKUP=/mnt/files2/FullMonth
 
# List with options exclude, include
# And lit of dirictories that need to backup
FILES_SRC=/mnt/files2/backup_src.lst
INCLUDE_FILES_PATTERN=/mnt/files2/backup_include.lst
EXCLUDE_FILES_PATTERN=/mnt/files2/backup_exclude.lst
 
# LOGS
LOG="/mnt/files/LOGS/archive.log"
ERRORLOG="/mnt/files/LOGS/archive_error.log"
#BIGLOG="/mnt/files/LOGS/big.log"
 
# TIME VARIABLES
TIMESTAMP=`date '+%Y-%m-%d_%H:%M:%S'`
DAY=`date '+%d'` # Day of week for INCREMENTIAL backup
DOW=`date '+%u'` # Day of week for Weekley backup (1..7); 1 is Monday, 7 is Sunday
DATE=`date '+%d-%m-%y_%H:%M'` # For FULL backup
DOM=`date +%d` # For Month backup
 
# DIRS VARIABLES
FULL_BACKUP_DIR=$BACKUP_DIR/current
INC_BACKUP_DIR=$BACKUP_DIR/$DAY\_$TIMESTAMP
 
echo "$(date +%F_%R:%S) #################### Start script ####################" >> $LOG
echo "" >> $LOG
echo "$(date +%F_%R:%S) #################### Start script ####################" >> $LOG
echo "" >> $LOG
 
# MONTHLY FULL BACKUP
if [ $DOM = "27" ]; then
        echo "$(date +%F_%R:%S) START OF MONTH BACKUP" >> $LOG
        echo "" >> $LOG
                if /usr/bin/tar -pczf /mnt/files2/temp/month1.tgz /mnt/files >> $LOG
                ls -lSh /mnt/files2/temp/month1.tgz >> $LOG
                mv /mnt/files2/FullMonth/month2.tgz /mnt/files2/FullMonth/month3.tgz >>$LOG
                mv /mnt/files2/FullMonth/month1.tgz /mnt/files2/FullMonth/month2.tgz >> $LOG
                mv /mnt/files2/temp/month1.tgz $MONTH_BACKUP/month1.tgz >> $LOG
                        then
                        echo "$(date +%F_%R:%S) MONTHLY ARCHIVING WAS DONE SUCCESFULL" >> $LOG
                        echo "" >> $LOG
                fi
fi
 
# WEEKLY FULL BACKUP
if [ $DOW = "3" ]; then
        echo "$(date +%F_%R:%S) START WEEKLY BACKUP" >> $LOG
        echo "" >> $LOG
                if /usr/bin/tar -pczf /mnt/files2/temp/week1.tgz /mnt/files >> $LOG
                ls -lSh /mnt/files2/temp/week1.tgz >> $LOG
                mv /mnt/files2/FullWeelky/week2.tgz /mnt/files2/FullWeelky/week3.tgz >> $LOG
                mv /mnt/files2/FullWeelky/week1.tgz /mnt/files2/FullWeelky/week2.tgz >> $LOG
                mv /mnt/files2/temp/week1.tgz $WEEKLY_BACKUP/week1.tgz >> $LOG
                        then
                        echo "$(date +%F_%R:%S) WEEKLY ARCHIVING WAS DONE SUCCESFULL" >> $LOG
                        echo "" >> $LOG
                fi
fi
 
rm -f -R $BACKUP_DIR/$DAY\_* >> $LOG
 
# INCREMENTIAL BACKUP WITH RSYNC
echo "$(date +%F_%R:%S) START INCREMENTAL BACKUP" >> $LOG
echo "" >> $LOG
nice -n 10 rsync -r --force --ignore-errors --delete --delete-excluded -av  \
--backup --backup-dir=$INC_BACKUP_DIR \
--exclude-from=$EXCLUDE_FILES_PATTERN \
--include-from=$INCLUDE_FILES_PATTERN \
--files-from=$FILES_SRC \
/ $FULL_BACKUP_DIR >> $LOG
 
rm -f $BACKUP_DIR/current\_*.tar.gz >> $LOG
cd $BACKUP_DIR >> $LOG
nice -n 10 tar -zcf $BACKUP_DIR/current\_$TIMESTAMP.tar.gz * >> $LOG
 
#IAM NOT SURE ABOUT MAIL
#mail -s "SVN backup log" alex@xxx.com < /mnt/files2/temp/backup.log
 
echo "" >> $LOG
echo "$(date +%F_%R:%S) ##################### End script #####################" >> $LOG
 
echo "" >> $ERRORLOG
echo "$(date +%F_%R:%S) ##################### End script #####################" >> $ERRORLOG

Разобраться в работе скрипта просто, он вроде хорошо прокомментирован. Некоторые пояснения:

  • в файле backup_exclude.lst пишем директории которые хотим исключить и не бэкапить
  • в файле backup_include.lst пишем директории которые хотим включить в бэкап (только если они не содержаться в файле backup_src.lst)
  • в файле backup_src.lst пишем директорию которую хотим бэкапить

Например у меня /mnt/files соответственно все что будет там, будет качественно забэкаплено, само собой rsync работает в скрипте рекурсивно, как и tar. Там еще есть строчка, которая может отправлять лог по почте, мне эта функция не пригодилась, но на всякий случай я ее не убрал.

Вчера забыл написать, добавлю сегодня, запускать скрипт желательно только в bash, т.е. в FreeNas это так:

/usr/local/bin/bash backRsync.sh

admin

1 Ответ

  1. Советую заменить строки
    # TIME VARIABLES
    TIMESTAMP=`date ‘+%Y-%m-%d_%H:%M:%S’`
    DAY=`date ‘+%d’` # Day of week for INCREMENTIAL backup
    DOW=`date ‘+%u’` # Day of week for Weekley backup (1..7); 1 is Monday, 7 is Sunday
    DATE=`date ‘+%d-%m-%y_%H:%M’` # For FULL backup
    DOM=`date +%d` # For Month backup

    на

    # TIME VARIABLES
    NOW=`date ‘+%Y-%m-%d %H:%M:%S’`
    TIMESTAMP=`date -d «$NOW» ‘+%Y-%m-%d_%H:%M:%S’`
    DAY=`date -d «$NOW» ‘+%d’` # Day of week for INCREMENTIAL backup
    DOW=`date -d «$NOW» ‘+%u’` # Day of week for Weekley backup (1..7); 1 is Monday, 7 is Sunday
    DATE=`date -d «$NOW» ‘+%d-%m-%y_%H:%M’` # For FULL backup
    DOM=`date -d «$NOW» +%d` # For Month backup

    Иначе в некоторых случаях, хоть и довольно редких, минуты в переменных TIMESTAMP и DATE могут различаться.

    А зачем $ERRORLOG ? В него же ни одна ошибка не записывается. Единственное место, где он используется это строки 90-91. Еще должно быть, как минимум, в строках, судя по всему, 33-34, то там простой лог. Да и в скрипте повсеместно вывод только stdout в лог, а stderr выводится только на консоль.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *