вторник, 1 декабря 2009 г.

BackUp. Резервное копирование на Linux/Unix.

Как известно проблемы различного характера лучше не исправлять, а предотвращать. Но время от времени приходится заниматься именно устранением последствий. Для системного администратора минимизировать отрицательные последствия после сбоя неполадок на сервере или потери какой-либо информации помогают системы резервного копирования (backup systems).

Для себя я написал небольшой скрипт для резервного копирования на операционных системах семейства Linux/Unix который даже имеет намек на модульность. Скрипт получился небольшой, простой и его легко можно модифицировать под ваши требования.

Я хочу поделиться с вами этим скриптом и в этой статье расскажу как его настроить.

Ссылка на вторую версию (она круче :) )
Про восстановление данных из резервной копии читайте тут.

Для начала давайте разберемся что же он все таки умеет.

В самом простом случае скрипт может создавать резервные копии локальных каталогов упаковывая их в tar.gzip. Папки можно группировать по архивам и добавлять исключения в пути как отдельных файлов, так и подкаталогов.

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

Есть так же два модуля для архивации баз данных PostgreSQL и MySQL.

Начнем с основного файла.

Нужно создать файл backup.sh и разрешить ему запускаться (chmod +x backup.sh). Содержимое файла следующее:

#!/bin/sh
SCRIPTDIR=/scripts/backup
BKPDIR="/www/backups/`hostname`"
MAPFILE="map.txt"
DATEYMD=`date "+%Y-%m-%d"`
ls ${SCRIPTDIR}/run|sort|while read EXECFIRST
do
env SCRIPTDIR=$SCRIPTDIR BKPDIR=$BKPDIR MAPFILE=$MAPFILE DATEYMD=$DATEYMD "${SCRIPTDIR}/run/$EXECFIRST"
done
cat ${MAPFILE}|sort|while read BKPFILES
do
mkdir -p ${BKPDIR}/${BKPFILES} 2>/dev/null
echo -n "">>"${BKPFILES}.x"
tar -zcvhf "${BKPDIR}/${BKPFILES}/${DATEYMD}-${BKPFILES}.tar.gz" --absolute-names --files-from="${BKPFILES}.bkp" --exclude-from="${BKPFILES}.x">"${BKPDIR}/${BKPFILES}/${DATEYMD}-${BKPFILES}.log"
done


Теперь о переменных:

SCRIPTDIR - папка со скриптом
BKPDIR - папка в которую будут складываться backup-ы
MAPFILE - файл со списком файлов с настройками архивов (чуть позже поймете)
DATEYMD - формат даты, которая добавляется к имени архива. Это сделано для удобного поиска нужного архива.

Это и есть тот страшный скрипт, но сам по себе он не заработает. Теперь ему нужно сказать что нужно backup-ить. Для этого в папке со скриптом создайте файл map.txt (или то что указанно в переменной MAPFILE).

В файле нужно перечислить категории архивов. В моем случае файл выглядел так:


configs
logs


Файл карты готов, теперь создаем файлы с категориями архивов. Для данного примера нужно создать 2 файла: configs.bkp и logs.bkp.

Пример содержания файла configs.bkp


/etc
/usr/local/etc


Пример содержания файла logs.bkp

/var/log

После первого запуска будут созданы файлы configs.x и logs.x (или другие для вашего варианта). Если вписать пути подкаталогов в эти файлы, то эти подкаталоги будут исключены из архива.

Ну в общем-то все готово. Можно пользоваться, но я говорил о намеке на модульность. Так вот в папке ./run запускаются все скрипты (которые разрешено запускать) и им передаются переменные основного скрипта.

Резервное копирование MySQL:


Создайте файл, например, mysql.sh, разрешите ему запускаться и добавьте:


#!/bin/sh
mkdir -p ${BKPDIR}/MySQL 2>/dev/null
mysqldump --databases -uUSER -pDLINNIYPASSWORD mysql| gzip -f -9 - >"${BKPDIR}/MySQL/${DATEYMD}-mysql-MySQL.gzip"
mysqldump --databases -uUSER -pESCHEODINPASSWORD phpmyadmin| gzip -f -9 - >"${BKPDIR}/MySQL/${DATEYMD}-phpmyadmin-MySQL.gzip"


Первая строчка создает подкаталог (если он еще не существует) в котором будут храниться резервные копии. Две другие строчки делают backup двух баз.

Резервное копирование PostgreSQL:


Создайте файл, например, postgresql.sh, разрешите ему запускаться и добавьте:


#!/bin/sh
mkdir -p ${BKPDIR}/PostgreSQL 2>/dev/null
(su - postgres -c "pg_dump postgres" <<EOF)| gzip -f -8 - >"${BKPDIR}/PostgreSQL/${DATEYMD}-postgres-PostgreSQL.gzip"
TUT_NUZNO_PISAT_PASSWORD_DLYA_BAZY
EOF

Резервное копирование MBR:



#!/bin/sh
mkdir -p ${BKPDIR}/MBR 2>/dev/null
dd if=/dev/sda of="${BKPDIR}/MBR/${DATEYMD}-sda-mbr.bin" bs=512 count=1

Для восстановления всей MBR надо запустить
dd if=sda-mbr.bin of=/dev/sdX bs=1

Для восстановления таблицы разделов нужно использовать
dd if= sda-mbr.bin of=/dev/sdX bs=1 count=64 skip=446 seek=446

Для восстановления только загрузчика запустите
dd if=sda-mbr.bin of=/dev/sdX bs=1 count=446


Скрипт (модуль) для резервного копирования файлов по маске:




#!/bin/sh
find /www -name '*.php' -or -name '*.js' -or -name '*.pl' -or -name '*.ephtml' -or -name '.htaccess' -or -name 'htpasswd' -or -name 'htgroup'>${SCRIPTDIR}/www.bkp
cat ${SCRIPTDIR}/${MAPFILE}|grep "www">/dev/null
if [ "$?" -eq 1 ]; then echo "">>${SCRIPTDIR}/${MAPFILE}; echo www>>${SCRIPTDIR}/${MAPFILE}; fi


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