Уже было много постов о резервном копировании, особенно много для ОС Linux. Озаботился и я настройкой резервного копирования.
Требовалось создавать бэкапы системы, данных с примонтированного раздела и LVM томов (диски виртуальных машин). Были мысли использовать Bacula, т.к. знаком с ней, но поскольку дома только 1 компьютер клиент-серверная архитектура только создавала-бы дополнительные сложности при восстановлении в случае повреждения системы. Значит систему и данные просто копируем, образ LVM раздела создаем с помощью dd. Хотелось делать резервную каждый день (хотя-бы данных) и хранить минимум 14 дней. Но поиски готовых и простых решений, удовлетворяющих всем потребностям не увенчались успехом. А значит берем в руки bash и пишем свой велосипед. В этой статье я делюсь тем, что вышло.
Disclaimer: при написании скриптов не было цели написать монстров, которые делают все. Нужен был простой и надежный способ бэкапа. Буду благодарен за указание неточностей и узких мест скриптов (тех, где могут возникнуть ошибки). Статья расчитана больше на новичков в Linux, которые ищут готовое решение и на лентяев 🙂 которым лень писать самим.
Исходные условия:
- ОС: Arch Linux
- Корневая файловая система (/): btrfs, копировать нужно все файлы.
- Раздел с данными (/mnt/data/): btrfs.
- LVM тома (/dev/virt_image_array/*).
- Раздел для бэкапов (/mnt/backup/: etx4, сюда будут складываться резервные копии.
- Необходимые утилиты (кроме входящих в базовый дистр): rsync, btrfs-progs (для управления btrfs).
Было решено раз в неделю делать полную копию всего и каждый день создавать снапшот разделов с btrfs. Можно так-же создавать снапшоты LVM томов, но для меня потеря данных за неделю не критична, поэтому хватит еженедельных копий.
Итак, скрипт № 1, создает копию файлов корневого раздела в /mnt/backup/root/«номер дня»/.
#!/bin/bash set -e echo "Date_start: `date +%Y-%m-%d-%H-%M-%S`" #Дата для удобного чтения логов ### Vars ### #Количество дней от точки отсчета (1970 год) day=$((`date +%s` / (60*60*24))) #Сколько дней хранить бэкапы dayexp=21 #Что копируем path="/" #Откуда копируем (путь до снапшота) spath="/snapshots/backup_script/" #Куда копируем dpath="/mnt/backup/root/" ### Delete Old Backups ### #Удаляем старые бэкапы find $dpath -type d 2>/dev/null| awk '{FS="/"} {print $5}'| sort|uniq | while read ONE_OF_LIST do if [[ "$ONE_OF_LIST" -lt "$day - $dayexp" ]] && [[ -n "$ONE_OF_LIST" ]] then echo "remove: $dpath$ONE_OF_LIST" rm -rf $dpath$ONE_OF_LIST fi done ### Check exist snapshot ### #Проверяем наличие снапшота, удаляем, если находим if (( "`btrfs subvolume list / | grep backup_script |wc -l`" > 0 )) then echo "Warning: Snapshot exist, deleting" btrfs subvolume delete $spath fi ### Create snapshot ### #Делаем снапшот btrfs subvolume snapshot / $spath ### Rsync ### #Копируем данные из снапшота rsync -aAXv $spath $dpath$day ### Delete snapshot ### #Удаляем снапшот btrfs subvolume delete $spath echo "Backup succesful complete" echo "Date_end: `date +%Y-%m-%d-%H-%M-%S`" exit 0
Скрипт № 2, создает снапшоты корневой ФС (скрипт логикой очень похож на 1й, поэтому коментировать буду только отличия). Снапшот имеет имя auto_«номер дня».
#!/bin/bash set -e echo "Date_start: `date +%Y-%m-%d-%H-%M-%S`" ### Vars ### day=$((`date +%s` / (60*60*24))) dayexp=14 path="/" spath="/snapshots/" ### Delete Old Backups / Check existing snapshot ### #Старые бэкапы удаляем, если находим сегодняшний снапшот выходим btrfs subvolume list / |grep auto |sed -e '1,$ s/.*_//g'| while read ONE_OF_LIST do if [[ "$ONE_OF_LIST" -lt "$day - $dayexp" ]] then echo "remove: $spath"auto_"$ONE_OF_LIST" btrfs subvolume delete $spath"auto_"$ONE_OF_LIST fi if [[ "$ONE_OF_LIST" -eq "$day" ]] then echo "Eroor: snapshot auto_$ONE_OF_LIST exist. Stop script execution." exit 1 fi done ### Create snapshot ### btrfs subvolume snapshot / $spath"auto_"$day ### End ### echo "Snapshot succesful created" echo "Date_end: `date +%Y-%m-%d-%H-%M-%S`" exit 0
Скрипт № 3, создает копию LVM тома:
#!/bin/bash set -e echo "Date_start: `date +%Y-%m-%d-%H-%M-%S`" ### Vars ### day=$((`date +%s` / (60*60*24))) dayexp=21 #Имя копируемого LVM тома path="/dev/virt_image_array/win_home_system" spath="/dev/virt_image_array/backup_lvm1" dpath="/mnt/backup/lvm1/" ### Delete Old Backups ### find $dpath -type d 2>/dev/null| awk '{FS="/"} {print $5}'| sort|uniq | while read ONE_OF_LIST do if [[ "$ONE_OF_LIST" -lt "$day - $dayexp" ]] && [[ -n "$ONE_OF_LIST" ]] then echo "remove: $dpath$ONE_OF_LIST" rm -rf $dpath$ONE_OF_LIST fi done ### Check exist snapshot ### #Проверяем отсутвие снапшота, удаляем, если находим if (( "`ls /dev/virt_image_array |grep backup_lvm1|wc -l`" > 0 )) then echo "Warning: Snapshot exist, deleting" lvremove --autobackup y -f $spath fi ### Create snapshot ### #Создаем снапшот, если на том идет активная запись, то можно увеличить место на снапшоте. Я сделал 10 Gb. lvcreate --size 10G --snapshot --name backup_lvm1 /dev/virt_image_array/win_home_system #Если у вас при создании снапшота спрашивает подтверждения на вайп сигнатуры используйте вариант с echo #echo "y"| lvcreate --size 10G -A y --snapshot --name backup_lvm1 /dev/virt_image_array/win_home_system ### DD ### #Можно поиграться с bs, у меня быстрей всего работает с 16M dd if=$spath of=$dpath$day bs=16M ### Delete snapshot ### lvremove --autobackup y -f $spath echo "Backup succesful complete" echo "Date_end: `date +%Y-%m-%d-%H-%M-%S`" exit 0
Поскольку скрипты, бэкапящие данные из /mnt/data аналогичны скриптам 1 и 2 думаю нет необходимости их писать.
Добавляем в crontab и определяем, как часто создавать бэкапы (в моем примере бэкап создается раз в неделю, снапшоты раз в день).
20 01 * * 1 /usr/bin/backup_root.sh >> /var/log/backup_root.log 2>&1 50 01 * * 1 /usr/bin/backup_lvm1.sh >> /var/log/backup_lvm.log 2>&1 20 01 * * * /usr/bin/snapshot_root.sh >> /var/log/snapshot_root.log 2>&1
Что еще можно прикрутить:
- Если нужно создавать больше бэкапов, а места нет, то можно поставить ФС с дедупликацией (например Opendedup), но снизится надежность хранения данных.
- В качестве хранилища может выступать папка подключенная по NFS или sshfs.
- Если нужно создавать бэкапы или снапшоты чаще, чем раз в день можно считать не дни с 1970 года, а часы (костыль, будет еще непонятней за какую дату бэкап).
ссылка на оригинал статьи http://habrahabr.ru/post/211917/
Добавить комментарий