Бэкап данных с btrfs и LVM bash скриптами

в 9:18, , рубрики: backup, btrfs, linux, LVM, бэкап, системное администрирование, метки: , , , ,

image

Уже было много постов о резервном копировании, особенно много для ОС 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/«номер дня»/.

Скрипт №1

#!/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_«номер дня».

Скрипт №2

#!/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 тома:

Скрипт №3

#!/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 года, а часы (костыль, будет еще непонятней за какую дату бэкап).

Автор: larrabee

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js