от Георги Теллалов(11-07-2005)

рейтинг (34)   [ добре ]  [ зле ]

Printer Friendly Вариант за отпечатване

Създаване на резервни копия с TAR

Всички знаем (поне на теория) колко важни са архивните копия на данните (backups). Много от нас са изпитвали и загубата на хард диск заедно с всички данни на него. На мен това ми се е случвало два пъти. Въпреки всичко малко от нас си правят копия на данните. Мисля, че причината в голяма степен е липсата на достатъчно лесен начин за това. Затова сега ще ви предложа едно елементарно решение на този проблем което разчита единствено на GNU tar (и по желание gzip или bzip2). Това решение се роди от нуждата за платформено независима система за архивиране, която да генерира леснодостъпни архиви (такива които да могат да се отварят и в най-спартански условия) и която не се нуждае никакви „специални“ функции.

Стратегия за архивиране

Пълен архив (или ниво 0) – всички данни, които трябва да се запазят.

Диференциален архив (всяко ниво над 0) – всички променени данни от последно архивиране от по-горно ниво.

Ето една примерна стратегия:

  • Ниво 0 – ежеседмично пълно копие на данните. Прави се всеки петък вечер в 18 часа.

  • Ниво 1 – ежедневно диференциално копие. Прави се всяка вечер в 18 часа (без петък).

  • Ниво 2 – ежечасно диференциално копие. Прави се на всеки час от 09 до 17.

При така описаната схема в случай на бедствие (например гръмнал хард диск) можем да възстановим данните си с максимална загуба на 1 час работа. Възстановяването протича така:

  • Разархивиране на ниво 0.

  • Разархивиране на последния диференциален архив от ниво 1.

  • Разархивиране на последния диференциален архив от ниво 2.

Решението Какво ще пазим?

Първият въпрос, който ще си зададем е „какво да запазим“? Добра идея е /etc, /home, /root. Към тях можем да добавим и някои специални нужди като /usr/local/bin (полезните шел скриптове, които сме си написали), /var/lib/iptables (ръчните настройки, които сме направили на защитната си стена), /var/lib/postgres (базата данни която използваме).

Какво няма да пазим?

Следва да се запитаме, какви изключения искаме да направим. Ако ще пазим данните си на ДВД със сигурност ще искаме да изключим значителната си колекция от mp3 музика и divx филми, тъй като вече ги имаме на оригиналните дискове, които сме си купили (или винаги можем да си ги свалим отново, ако авторите им ги разпространяват свободно). Да кажем, че те ни стоят в /home/multimedia. Искаме да изключим и свободния софтуер, който си сваляме от Интернет, защото винаги можем да си го свалим отново (/home/downloads). Накрая ще изключим и всичко от /usr/local/bin, което не е шел скрипт (т.е. не завършва на .sh), защото не ни трябва архив на изпълнимите файлове, които сме си компилирали от сорс.

Как ще се подготвим?

Какво трябва да направи компютърът преди да започне архивирането на данните? Трябва да спре всички програми, които биха могли да записват данни, които ще архивираме. Например ако използваме postgres бази данни трябва да спрем сървъра и да сме сигурни, че не се изпълнява „почистване“ на базата (vaccum). Това се налага, защото ако копираме файловете и в същото време някоя програма записва нова информация в тях можем да свършим с частично копие, което няма да работи, ако се наложи възстановяване от архивите.

Параметрите на tar

За яснота ще използвам дългите варианти на опциите на tar.

Архивът се създава с опция –create и се запазва във файла указан от опция –file. Ако искаме да спестим място (за сметка на по-дълго време за създаване на архива) можем да използваме опция –gzip или –bzip за компресиране.

GNU tar може да създава два вида диференциални архиви. Старият формат (–incremental) създава нестандартни архиви, които може да не се четат от не-GNU версии на tar. Затова аз предпочитам новия (–listed-incremental). Той създава отделен описателен файл, съдържащ списък на всички директории, включени в архива. Този списък е необходим, за да бъде създаден диференциалният архив от следващо ниво както и при възстановяване на данните от архива.

Остава най-важното – да укажем какво ще включим и какво ще изключим от архива. Най-лесно е двата списъка да се съхраняват във файлове и да инструктираме tar да ги чете оттам. Файлът съдържащ елементите за архивиране се задава с опция –files-from, а този съдържащ изключенията – с –exclude-from. Тези файлове ще бъдат съответно /etc/backup/do-backup и /etc/backup/do-not-backup.

Ето как изглежда окончателната ни команда за създаване на пълен архив:

tar –create –file=/backup/level0-backup.tar –listed-incremental=/backup/level0-backup.list \

–files-from=/etc/backup/do-backup –exclude-from=/etc/backup/do-not-backup

Резултатът от изпълнението са два файла – level0-backup.tar, който е стандартен tar архив и level0-backup.list, който е обикновен текстов файл.

Да създадем и един архив от ниво 1:

tar –create –file=/backup/level1-backup.tar –listed-incremental=/backup/level1-backup.list \

–files-from=/etc/backup/do-backup –exclude-from=/etc/backup/do-not-backup

Забележете, че използваме друг описателен файл (level1-backup.list, а не level0-backup.list). За да постигнем наистина каквото искаме, т.е. архив от ниво 1, трябва предварително да сме копирали level0-backup.list в level1-backup.list. За да разберем, как точно работи това, трябва да се задълбочим в ръководството на tar. На моята Дебиан система man tar предлага поглед от доста високо. Подробностите са скрити в info tar. Там четем, че опцията –listed-incremental използва указания й като параметър файл, за да създаде диференциален архив или създава нов файл, ако указаният не съществува като при това включва всичко избрано в архива (т.е. създава архив от ниво 0). Накратко казано, когато искаме да създадем диференциален архив трябва да използваме вече съществуващ описателен файл. Копирането се налага, защото tar променя описателния файл, като включва в него само директориите, които съдържат промени. Така ако използваме оригиналния описателен файл, той ще бъде променен и няма да сме в състояние да създаваме повече архиви от същото ниво.

Не се оставяйте да ви объркам с тези обяснения – в следващата глава мъглата се разсейва с примери!

Автоматизация

Глава за напреднали потребители. Тези които не се интересуват от техническите подробности могат да прескочат направо на глава Използване.

Всичко казано дотук сигурно звучи много добре на теория (поне аз се надявам така, защото обратното би означавало, че никак не ме бива в обясненията), но тръгнем ли да го прилагаме на практика, много скоро ще открием, че решението далеч не е това, което статията претендира да е – лесно за използване. Въвеждането на команда от два реда всеки ден (а за някои читатели и по-често), е всичко друго, но не лесно, или бързо, или удобно. Да не говорим, че това далеч не е единствената команда – особено ако искаме да записваме архивите на ДВД. Затова ще трябва да улесним живота си с малко автоматизация. За целта ще прибегнем до услугите на GNU bash. Преди да продължа искам да се извиня на тези от вас, които все още помнят първоначалното ми твърдение, че решението е базирано само на GNU tar – виноват!

Документацията на tar говори за готови скриптове – backup и restore – част от пакета tar. В моята инсталация тези скриптове не присъстват.

И така нека си създадем два допълнителни файла – backup.sh и options. Скрипта backup.sh ще поставим в любимата си директория за изпълними файлове, която е включена в пътищата ни (/usr/local/bin е една добра идея), а конфигурационния файл options ще добавим към /etc/backup.

Съдържанието на backup.sh и коментарите към него следват:


1 #!/bin/bash

2

3 LEVEL=""

4 for i; do

5 case "$i" in

6 --level*)

7 LEVEL=${i#*=}

8 ;;

9 esac

10 done

11

12 test -z "$LEVEL" && echo "No level selected" && exit 1

13

14 test -f /etc/backup/options && . /etc/backup/options

15

16 test -z "$DESTINATION_PATH" && echo "Missing destination path" && exit 2

17

18 NOW=$(date +%Y-%m-%d-%H-%M)

19 ARCHIVE_FILE="${DESTINATION_PATH}/${HOSTNAME}-level${LEVEL}-${NOW}.tar.bz2"

20 LIST_FILE="${DESTINATION_PATH}/${HOSTNAME}-level${LEVEL}-${NOW}.list"

21

22 if [ $LEVEL -gt 0 ]; then

23 LOW_LEVEL=$((LEVEL-1))

24 LAST_LIST_FILE=$(ls "${DESTINATION_PATH}/${HOSTNAME}-level${LOW_LEVEL}"*list 2>/dev/null | tail -1)

25 test -z "$LAST_LIST_FILE" && echo "Level $LOW_LEVEL backup not found" && exit 3

26 cp "$LAST_LIST_FILE" "$LIST_FILE"

27 fi

28

29 /etc/init.d/postgresql stop

30 tar --create --listed-incremental="$LIST_FILE" --file="$ARCHIVE_FILE" \

31 --directory=/ --exclude-from=/etc/backup/do-not-backup \

32 --files-from=/etc/backup/do-backup

33 /etc/init.d/postgresql start


Редове от 3 до 10 обработват единствения параметър на скрипта – нивото на архива, който ще бъде създаден. Ред 14 зарежда конфигурационния файл в случай, че е наличен. Редове 19 и 20 дефинират имената на архивния и описателния файл. Нека обърнем внимание, че имената са малко по-описателни от примерите в предната глава. Те съдържат името на компютъра (hostname), чийто данни се архивират, както и датата и часа на създаването на архива. Датата и часът се представят във формат ГОДИНА-МЕСЕЦ-ДЕН-ЧАС-МИНУТИ (ред 18).

Най-интересната част от скрипта са редове от 22 до 27. Те осигуряват създаването на архиви от ниво 1 и по-високи следвайки много прост алгоритъм. Всяко ниво над 0 се създава като се базираме на последния архив от едно ниво по-долу. Редове 24 до 26 копират последния описателен файл от по-долното ниво в описателния файл на текущото ниво и редове 30 до 32 създават новия диференциален архив на базата на този описателен файл.

Преди създаването на архива се спират всички услуги, които могат да му попречат (ред 29) и след това се пускат наново (ред 33).


Да разгледаме и /etc/backup/options:

1 DESTINATION_PATH="/backup"


В настоящата си версия не е особено богат на съдържание и спокойно може да бъде преместен в backup.sh. Направил съм го така, за да бъде по-прегледно в случай, че в бъдеще се появи нуждата от повече настройки.


Ето и примерното съдържание на /etc/backup/do-backup:

1 usr/local/bin

2 etc

3 home

4 var/lib/iptables

5 var/lib/postgres

6 root


Следва /etc/backup/do-not-backup:

1 usr/local/bin/*[^.][^s][^h]

2 home/multimedia

3 home/downloads


Използване
  • Изтегляме си файловете описани в статията от тук.

  • Разархивираме с командата tar -C / -xvvf backup.tar (от root shell)

Сега вече можем да създадем първия си пълен архив с командата:

backup.sh –level=0

Така създаденият архив се намира в /backup. Сега можем да си го запишем на СД/ДВД с любимата си програма или да го запазим на друго място по избран от нас начин.

Напълно автоматично архивиране се постига с помощта на /etc/crontab, но това е извън обхвата на статията.

Възстановяването от архива може да стане по два начина:

  1. tar –extract –file=/backup/.tar

  2. tar –extract –file=/backup/.tar –listed-incremental=/backup/.list

Разликата е, че вторият вариант ще изтрие всички файлове, които не присъстват в архива. Той се използва за възстановяване на точното състояние на файловата система към момента на архивирането. С него трябва да се внимава, защото ако искаме само да възстановим изтрит по грешка файл, можем да завършим с изтриване на други файлове, които още нямаме архивирани.

Заключение

Разгледахме решение, което е ориентирано към обикновени потребители със скромни нужди. То е достатъчно гъвкаво, за да бъде използвано на всеки Юникс вариант, който разполага с bash и GNU tar, както и на Уиндоус с помощта на cygwin или msys. Така създадените архиви могат да бъдат записвани върху лентови устройства, презаписваеми оптични носители, мрежови складове и т.н. Например за добавяне на нов диференциален архив върху презаписваемо ДВД можем да използваме следната команда:

growisofs -M /dev/dvd -R -J /backup/.*

Някои пътища в използваните примери са специфични за Дебиан ГНУ/Линукс и може да се нуждаят от промяна за да работят на други ОС.


Тази статия (при това добре форматирана) е достъпна също в OpenOffice и HTML формат.

Приемам предложения за подобрение под формата на кръпки на адрес gtellalov на bigfoot.com.




<< amaroK - next generation multimedia player | Виртуален тунел на базата на Linux -2 >>