Мой подход к бекапу файлов, БД под Centos

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

Я бекаплюсь по такой схеме:

  • раз в два дня, глухой-темной ночью ), делается бекап базы (mysql)
  • раз в четыре дня, глухой-темной ночью ), делается бекап сайтов (статика, сорцы, темплейты и т.д.)
  • каждый первый день месяца, делается бекап системных папок, бекаплю только /etc/, т.к. в бекапе других папок не вижу особого смысла
  • раз в четыре дня другая машина конектится к основному серверу и забирает последние архивы

В начале каждого скрипта есть набор переменных, в которых просто меняете значения на свои.

Скрипт для бекапа mysql-базы. Мне бекапить все базы не надо, поэтому я в переменной DB_LIST храню список тех баз, что необходимо сохранить. Файлы старше 10 дней (переменная FILES_OLDER_THAN) автоматически удаляются.

### system setup ###

GZIP="$(which gzip)"
NOW=$(date +"%d-%m-%Y")

### mysql setup ###
# view all dbs: mysql -u admin -h localhost -p -Bse 'show databases'

DB_LIST="db1 db2 db3"
DB_USER="root"
DB_PASS="qwerty"
DB_HOST="localhost"
MYSQL="$(which mysql)"
MYSQLDUMP="$(which mysqldump)"
DB_BACKUP_DIR=/home/proft/backup/db
FILES_OLDER_THAN=10 #days

# backup dbs

for DB in $DB_LIST; do
    DB_DIR=$DB_BACKUP_DIR/$DB
    if [ ! -d "$DB_DIR" ]; then
        mkdir -p $DB_DIR
    fi

    FILE=$DB_DIR/mysql-$DB-$NOW.gz
    $MYSQLDUMP -u $DB_USER -h $DB_HOST -p$DB_PASS $DB | $GZIP -9 > $FILE
done

# delete files older than $DB_OLDER_THAN days
find $DB_BACKUP_DIR -type f -mtime +$FILES_OLDER_THAN -exec rm {} \;

Скрипт который бекапит содержимое папок с сайтами. Я хочу что-бы каждый архив имел вид www-Имя_Сайта-Дата.tar.gz. Первая идея которая пришла в голову - ассоциативные массивы (хэши), в ключе хранится Имя_Сайта в значении - путь к сайту в файловой системе. Но bash поддерживает хеши начиная с версии 4, а на сервере стоит bash 3.2, делать апдейт я поленился :). Второе решение, более примитивное, завести два отдельных массива, в одном хранить названия сайтов (переменная WWW_NAMES), в другом - пути к сайтам (переменная WWW_PATHS). Файлы старше 10 дней (переменная FILES_OLDER_THAN) автоматически удаляются.

### system setup ###

GZIP="$(which gzip)"
NOW=$(date +"%d-%m-%Y")

### www dirs setup ###

WWW_NAMES=("www1" "www2" "www3")
WWW_PATHS=("/srv/www/www1/" "/srv/www/www2/" "/srv/www/www3/")

WWW_BACKUP_DIR=/home/proft/backup/www
FILES_OLDER_THAN=10 #days

# backup www

for WWW in ${!WWW_NAMES[*]}; do
    WWW_DIR=$WWW_BACKUP_DIR/${WWW_NAMES[$WWW]}
    if [ ! -d "$WWW_DIR" ]; then
        mkdir -p $WWW_DIR
    fi

    FILE=$WWW_DIR/www-${WWW_NAMES[$WWW]}-$NOW.tar.gz
    tar -zcf $FILE ${WWW_PATHS[$WWW]}
done

# delete files older than $DB_OLDER_THAN days
find $WWW_BACKUP_DIR -type f -mtime +$FILES_OLDER_THAN -exec rm {} \;

Скрипт бекапа системных папок похож один в один на предыдущий, только в массиве SYS_NAMES хранятся имена системных папок, а в массиве SYS_PATHS пути к ним.

### system setup ###

GZIP="$(which gzip)"
NOW=$(date +"%d-%m-%Y")

### sys dirs setup ###

SYS_NAMES=("etc")
SYS_PATHS=("/etc/")

SYS_BACKUP_DIR=/home/proft/backup/sys
FILES_OLDER_THAN=10

# backup sys

for SYS in ${!SYS_NAMES[*]}; do
    SYS_DIR=$SYS_BACKUP_DIR/${SYS_NAMES[$SYS]}
    if [ ! -d "$SYS_DIR" ]; then
        mkdir -p $SYS_DIR
    fi

    FILE=$SYS_DIR/${SYS_NAMES[$SYS]}-$NOW.tar.gz
    tar -zcf $FILE ${SYS_PATHS[$SYS]}
done

# delete files older than $DB_OLDER_THAN days
find $SYS_BACKUP_DIR -type f -mtime +$FILES_OLDER_THAN -exec rm {} \;

Запускаем cron:

crontab -e

и говорим когда запускать скрипты

20      0       */2     *       *       /home/proft/backup/db.sh >/dev/null 2>&1
40      0       */5     *       *       /home/proft/backup/www.sh >/dev/null 2>&1
0       1       1       *       *       root    /home/proft/backup/sys.sh >/dev/null 2>&1

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

DB_BACKUP_DIR=/home/proft/backup/db
WWW_BACKUP_DIR=/home/proft/backup/www
SYS_BACKUP_DIR=/home/proft/backup/sys

# list last backups

for dir in $DB_BACKUP_DIR/* $WWW_BACKUP_DIR/* $SYS_BACKUP_DIR/*; do
    last_file=`ls -t1 $dir | head -n1`
    echo $dir/$last_file
done

Скрипт который находится на другой машине, которая конектится по ssh к основному серверу и забирает последние архивы.

DB_BACKUP_DIR=/home/proft/backup/db
WWW_BACKUP_DIR=/home/proft/backup/www
SYS_BACKUP_DIR=/home/proft/backup/sys

# list last backups

for dir in $DB_BACKUP_DIR/* $WWW_BACKUP_DIR/* $SYS_BACKUP_DIR/*; do
    last_file=`ls -t1 $dir | head -n1`
    echo $dir/$last_file
done

В скрипте есть один изъян - он на протяжении месяца забирает один и тот же файл несколько раз (системные папки, которые бекапятся раз в месяц), но меня это почти устраивает и что-то допиливать пока лень.

Буду рад советам, рекомендациям бывалых админов.

Все скрипты одним архивом, пользуйтесь на здоровье :).

Дополнительное чтиво:

blog comments powered by Disqus