Резервное копирование
Материал из RSU WiKi
Содержание |
Образ HDD при помощи dd
Для того, чтобы сделать резервную копию (файл-образ) винчестера для последующего восстановления вовсе не нужны коммерческие, проприетарные утилиты - есть старый, как мир, dd. Всё, что нужно сделать - просто правильно его использовать.
Утилита dd есть в любом дистрибутиве, и даже в Knoppix, который можно использовать для восстановления данных. Для этого так же потребуется любой архиватор, в данном примере это gzip. Приведён вариант с архивированием на другую машину по сети с использованием SSH или netcat.
Приготовления
Загружаемся с любого LiveCD диска с Линукс / BSD, залогиниваемся под root-аккаунтом. Убеждаемся, написав в консоли df, что ни один из тех разделов, что мы собираемся копировать, не примонтирована на запись. Решаем, куда будем архивировать данные: это может быть другой раздел на винчестере, внешний жёсткий диск или по сети.
Создаём резервную копию
В данном примере /dev/hda это винчестер, который архивируем, а /dev/sda1 - это раздел внешнего винчестера или другая партиция, на которую архивируем, hda.img.gz - получившийся сжатый файл-образ.
Внешний винчестер или другой раздел диска
Монтируем устройство, куда мы будем архивировать данные
# mount -t vfat /dev/sda1 /mnt/sda1
Перегоняем данные с одного винчестера на другой. Так как данных много, полезно их сжать - и никс-системы позволяют это делать "на лету". В примере использван GZip, но подойдёт и любой другой (например, bzip2 или p7zip).
Hint: Чтобы образ HDD лучше сжимался [1] перед архивированием на нем можно выполнить вот такуюю команду:
# dd if=/dev/zero of=/mnt/sda1/eraseFreeSpace bs=1m; rm /mnt/sda1/eraseFreeSpace
Архивируем:
# dd if=/dev/hda conv=sync,noerror bs=1M | gzip -c > /mnt/sda1/hda.img.gz
Здесь происходит архивирование с одновременным сжатием, результат чего записывается в файл hda.img.gz
Параметр "conv=sync,noerror" указывает dd не читать блок, если при этом происходит ошибка, но записать в архивируемый файл-образ данные, чтобы размер блока не менялся.
Параметр "bs=1M" это размер блока в мегабайтах (лучше сделать еще больше, а именно равным размеру кеша копируемого диска; т.е. например bs=8m, это сильно ускорит весь процесс) - использование такого большого размера блока ускоряет процесс копирования. Выходной поток передаётся по конвейеру для сжатия gzip, результат выводится в файл на другом диске.
Иногда (на ФС, отличных от ext3/reiser/xfs) возникают проблемы с файлами больше 2х или 4х Гб. Чтобы предотвратить такие проблемы, файл образа можно сразу порезать split-ом:
# dd if=/dev/hdb1 | gzip | split -d -b 2G hdb1_img_
Получатся файлы hdb1_img_0, _1, ...
Удалённо по сети
Всё то же самое, что в п.2.1, но с добавлением в конвейер SSH:
# dd if=/dev/hda conv=sync,noerror bs=64K | gzip -c | ssh -c blowfish user@hostname "dd of=hda.img.gz bs=64k"
Архивный файл появится в домашней директории пользователя user на машине hostname. Если сеть маленькая, лучше вместо hostname использовать просто ip-адрес. Опция -c blowfish заставляет SSH выбрать алгоритм шифрования Blowfish, который быстрее остальных шифрует данные.
Вариант с netcat, если данные копируются по локальной сети и шифрование не нужно:
# dd if=/dev/hda conv=sync,noerror bs=64K | gzip -c | nc 192.0.2.1 3333
На удалённой машине должен быть запущен netcat:
# nc -l -p 3333 > hda.img.gz
Вариант с SAMBA, если копирование производится на оффтопичную машину: примонтировать удалённо сетевой ресурс
# smbmount //192.0.2.100/shared /mnt/remoteshare -o username=имяпользователя,password=пароль
и далее всё то же, что и в п.2.1.
Восстанавливаем данные из резервной копии
Пример тот же: /dev/hda это винчестер, который архивируем, hda.img.gz - архивный сжатый файл-образ, а /dev/sda1 - это раздел внешнего винчестера или другая партиция, с которого восстанавливаем данные.
Внешний винчестер или другой раздел диска
Копируем и распаковываем файл-образ одновременно:
# gzip -x /mnt/sda1/hda.img.gz | dd of=/dev/hda conv=sync,noerror bs=64K
Все параметры в п.2 уже объяснены.
Удалённо по сети
Сетевой вариант с восстановлением из файл-образа:
# dd if=hda.img.gz | ssh -c blowfish user@deadhost.example.com "gunzip -c | dd of=/dev/hda1 bs=64k"
Следует помнить, что в данном случае не следует использовать опцию conv=sync,noerror в опциях dd - если вы всё-таки включите эту опцию, в большинстве случаев это исказит записываемые данные (это заставляет dd не дожидаться данных, приходящих по сети, если целый блок недоступен).
Инкрементальное копирование данных при помощи bontmia
Скачиваем скрипт вот отсюда: http://folk.uio.no/johnen/bontmia/
Archive structure
The archives is placed in a directory structure like this:
2003/05/06/04:00/ 2003/05/07/04:00/ 2003/05/08/04:00/ 2003/05/08/05:00/ 2003/05/08/06:44/
which is YYYY/MM/DD/HH:MM/ when the backup was issued. Since the granularity of the backup archives is one minute there is not possible to run two different backups within the same minute.
Under these directories the archived files and directories is stored within a directory named the hostname backed up and absolute path. Like this:
2003/05/06/04:00/foo:/home/jev
/bar:/home/jev
/baz:/home/jev
2003/05/07/04:00/foo:/home/jev
/bar:/home/jev
/baz:/home/jev
Operation
The following shows an example of how to do backup once every day and keep the last 7 days, 4 weeks, 12 monthly and 2 years. The hostname is changed.
$ bontmia --dest ./backup --rotation \
0minutes0hours7days4weeks12month2years \
foo.bar.com:/home/jev \
foo.bar.com:/etc \
foo.bar.com:/usr/local \
foo.bar.com:/var
When this is run it outputs the following on my system (the hostname is changed). Since the computer have not been on all the time not all the backups have been run but the last x backups is saved for each filter. Which filter that is active for each backup is shown. The one removed is not longer filtered to be saved.
Making a hard-link replication of the last backup (/backup/2003/09/20/00:00) Backing up by modifying the replication foo.bar.com:/home/jev foo.bar.com:/etc foo.bar.com:/usr/local foo.bar.com:/var Deletes files that should not be in the latest snapshot Moving the complete backup into the backup archive (/backup/unfinished_backup -> /backup/ Calculates which backups to save Saving /backup/2003/06/29/19:07 by filters: month Saving /backup/2003/07/20/10:00 by filters: month Saving /backup/2003/08/26/22:30 by filters: weeks month Saving /backup/2003/09/07/00:00 by filters: weeks Removing /backup/2003/09/13/00:00 Saving /backup/2003/09/14/00:00 by filters: days weeks Saving /backup/2003/09/15/00:00 by filters: days Saving /backup/2003/09/16/00:00 by filters: days Saving /backup/2003/09/17/00:00 by filters: days Saving /backup/2003/09/18/00:00 by filters: days Saving /backup/2003/09/19/00:00 by filters: days Saving /backup/2003/09/20/00:00 by filters: days weeks month years
As one can see the last 7 days is saved, the last 4 weeks is saved and the last 3 month is saved. The backup have only run for the last 3 month and therefore there is no more month backups. Similar for the year backup.
NB! If you want to make copies of several directories then do not run Bontmia multiple times against the same '--dest' but instead list each source directory as arguments on one command or the incremental storage becomes impossible to maintain and one end up copying all the data all the time.
MySQL
Резервное копирование отдельных баз при помощи mysqldump
Предположим что на сервере MySQL есть пользователь backup-user с правами read-only для всех интересующих нас баз. В примере используются database1, database2, database3 и database4.
Скрипт для cron.daily, хранит ежедневные копии последних 7 дней:
#!/bin/bash
USNAME="backup-user"
USPASS="backup-pass"
DATE_DAILY=`date +%F`
mkdir /backup/sql/daily/$DATE_DAILY
echo -n .
for i in database1 database2 database3 database4;
do
mysqldump -u $USNAME -p$USPASS $i | bzip2 > /backup/sql/daily/$DATE_DAILY/$i.sql.bz2
echo -n .
done
find /backup/sql/daily \! -type d -mtime +6 -exec rm {} \;
rmdir /backup/sql/daily/*
Скрипт для cron.weekly, хранит копии последних 4 недель:
#!/bin/bash
USNAME="backup-user"
USPASS="backup-pass"
DATE_WEEKLY=`date +%V`
mkdir /backup/sql/weekly/$DATE_WEEKLY
echo -n .
for i in database1 database2 database3 database4;
do
mysqldump -u $USNAME -p$USPASS $i | bzip2 > /backup/sql/weekly/$DATE_WEEKLY/$i.sql.bz2
echo -n .
done
find /backup/sql/weekly \! -type d -mtime +21 -exec rm {} \;
rmdir /backup/sql/weekly/*
Скрипт для cron.monthly, хранит 2 последних месяца:
#!/bin/bash
USNAME="backup-user"
USPASS="backup-pass"
DATE_MONTHLY=`date +%m`
mkdir /backup/sql/weekly/$DATE_WEEKLY
echo -n .
for i in database1 database2 database3 database4;
do
mysqldump -u $USNAME -p$USPASS $i | bzip2 > /backup/sql/monthly/$DATE_MONTHLY/$i.sql.bz2
echo -n .
done
find /backup/sql/monthly \! -type d -mtime +60 -exec rm {} \;
rmdir /backup/sql/monthly/*
Ссылки
Пример
Создание резервной копии
#!/bin/bash
USNAME="backup"
USPASS="pass"
DATE=`date +%d.%m.%Y`
BACKUPDIR="/storage/BACKUP"
cd /
bontmia --dest $BACKUPDIR --rotation \
0minutes0hours7days2weeks3month1years \
ns.rspu:/var/lib/named/ \
ns.rspu:/srv/www/ \
ns.rspu:/var/lib/rrd/ \
ns.rspu:/etc/ \
ns.rspu:/usr/local/ \
www.rspu:/srv/www/ \
www.rspu:/etc/ \
www.rspu:/usr/local/ \
mail.rspu:/opt/CommuniGate/ \
mail.rspu:/etc/ \
mail.rspu:/usr/local/ \
mail.rspu:/var/CommuniGate/Accounts/ \
mail.rspu:/var/CommuniGate/CGI/ \
mail.rspu:/var/CommuniGate/Directory/ \
mail.rspu:/var/CommuniGate/Domains/ \
mail.rspu:/var/CommuniGate/PBXApps/ \
mail.rspu:/var/CommuniGate/Settings/ \
mail.rspu:/var/CommuniGate/WebSkins/ \
mail.rspu:/var/CommuniGate/cgpav \
proxy.rspu:/etc/ \
proxy.rspu:/usr/local/ \
proxy.rspu:/usr/share/squid/errors/ \
proxy.rspu:/srv/www/htdocs/
# Additional SQL backup process
echo "Dumpin' mysql databases:"
mkdir $BACKUPDIR/$DATE-www-sql/
for i in dbase dbase1 dbase2 dbase3;
do
echo -n " Processing " $i"... "
mysqldump -h k-web.rspu -u $USNAME -p$USPASS $i | bzip2 > $BACKUPDIR/$DATE-www-sql/$i.sql.bz2
echo " Done!"
done
echo "SQL bakup porcess completed!"
#find . -type d -empty -print0 | xargs -0 rmdir
Подготовка резервной копии к записи на DVD
#!/bin/bash BACKUPDIR="/storage/BACKUP" BACKUPBURN=$BACKUPDIR"/burn" DATE=`date +%Y-%m-%d` #LASTY=`ls -1 $BACKUPDIR|tail -1` LASTY=`date +%Y` LASTM=`ls -1 $BACKUPDIR/$LASTY/|tail -1` LASTD=`ls -1 $BACKUPDIR/$LASTY/$LASTM|tail -1` #echo "Path: /" $LASTY "/" $LASTM "/" $LASTD mkdir $BACKUPBURN tar -cvpj $BACKUPDIR/$LASTY/$LASTM/$LASTD/ $BACKUPDIR/$LASTD.$LASTM.$LASTY-www-sql | split -d -b 4200m - $BACKUPBURN/archive-$DATE.tar.bz2.

