
\section{Забота о сохранности данных}

 Известно, что пока рак на горе не свистнет, мужик не перекрестится.
Большинство пользователей понимает необходимость в ведении архива резервных
копий лишь после серьёзной потери важных данных и полученного в результате
нагоняя от начальства. Иногда это бывает весьма больно и обидно. Ещё
больнее обиднее, когда теряются свои, личные данные - любимый 
фотоальбом, архив старых добрых игрушек, почтовый ящик, где 
была переписка с виртуальной любовницей. Конечно же, хочется всё испытать на
себе, и самостоятельно убедиться в ненадёжности систем хранения данных ---
но мы бы не советовали. Проще учиться на чужих ошибках.

 Итак, компьютер --- система далеко не надёжная, подверженная действию
законов Мерфи, как и вообще любая созданная человеком или природой техника.
Кроме естественных причин, таких, как физическая неисправность оборудования,
прямое попадание метеорита в системный блок, террористические акты, пролитый
куда не следует чай или зря подвернувшаяся под руку в минуты гнева кувалда,
есть и внутренние предпосылки к порче и потере данных --- ошибки или
недоделки в программном обеспечении, неосторожные действия
пользователя, некорректная организация самих данных. Абсолютной сохранности
данных, на уровне ``рукописи не горят'', гарантировать не может ничто, но
стоит хотя бы немного повысить надёжность системы и застраховать себя от 
наиболее частых случайностей. Один из основных и наиболее простых способов
подобной страховки --- ведение архива резервных копий. Далее мы рассмотрим
некоторые общие принципы и простые примеры реализации архива.

% ....

 Для организации системы сохранения резервных копий пользовательских данных
требуется определить:
\begin{itemize}
\item список собственно нуждающихся в регулярном сохранении файлов и
каталогов
\item технические возможности выбранных для резервного копирования носителей
\item полный объём выбранных для спасения данных и скорость накопления
изменений в них
\end{itemize}

 Рассмотрим простой пример --- у пользователя есть cvs--репозиторий, где он
хранит свои текстовые документы и файлы конфигурации, расположенный
в {\tt /home/user/cvsroot/}, область для закачки несистематизированных
файлов из Internet--а в {\tt /home/user/downloads/}, систематизированный
архив в {\tt /home/user/archive/}, почтовые ящики в {\tt /home/user/mail/},
и директория с временными рабочими файлами {\tt /home/user/work/}.

 Как видим, все эти каталоги содержат весьма разнородную информацию,
требующую разных подходов к ведению архива резервных копий. Попробуем
выбрать наиболее оптимальную технологию для данного (весьма характерного) 
случая. Для начала перечислим известные факты:

\begin{enumerate}
\item CVS--репозиторий уже сам по себе содержит всю информацию об
изменениях, и имеет достаточно малый размер. Следовательно, нет
необходимости в инкрементальном backup--е, и нет необходимости хранить
большое число устаревших копий --- всегда достаточно одной.
\item каталог с несистематизированными файлами быстро меняется, и файлы из
него либо удаляются за ненадобностью, либо переходят в систематизированную
область.
\item каталог с систематизированным архивом имеет большой размер, и все
возможные его изменения --- это лишь добавление новых файлов. Здесь
определённо требуется инкрементальный backup.
\item почтовые ящики --- здесь самый сложный случай. Сами файлы тут
регулярно изменяются, в основном на дополнение (дописывание в конец), иногда
удаление, и некоторые изменения в заголовках писем, содержащие информацию о
просмотре и наличии ответа. Однако, под CVS пользователь их не содержит ---
не целесообразно, при том, что некоторая функциональность системы контроля
версий при сохранении резервной копии нам здесь определённо потребуется.
\item временные рабочие файлы по сути своей близки к каталогу
несистематизированных файлов, и обрабатывать их будем одним методом.
\end{enumerate}

 Оценим (точнее, придумаем) технические возможности. Возьмём более--менее
популярную ситуацию --- пользовательские файлы ({\tt /home/user/})
расположены на быстром локальном диске, кроме того, на этой же машине есть
второй, медленный жесткий диск --- считаем его более надёжным, так как
используется файловая система ext3 c --journal-data, и он
реализован как софтовый RAID--массив (mirror) из двух одинаковых жестких
дисков. Так же имеется в наличии устройство записи CDRW--дисков (но нет
файловой системы UDF, дабы ситуация походила на использование ленточного
накопителя). Финансовые возможности нашего пользователя
ограниченны, так что он может себе позволить выделить под резервное
копирование лишь 6 болванок. Промаркируем их заранее как ``Backup disk 1'',
``Backup disk 2'', ..., ``Backup disk 6''.

 Будем считать, что на "надёжном" диске заведомо есть свободное
пространство, в 4 раза превышающее объём, занятый пользовательскими файлами,
подлежащими резервному копированию. 

 Итак, приступим к построению полуавтоматической системы ведения архива
резервных копий. У нас будет три этапа:
\begin{itemize}
\item ведение зеркала на медленном диске
\item накопление инкрементального архива для последующей записи на CDRW
\item запись на CDRW, с ротацией и уплотнением инкрементальных архивов.
\end{itemize}

 Первый этап реализуется весьма элементарно, с помощью утилиты rsync.

%%% файл homesync.sh
\begin{verbatim}
#!/bin/sh

mkdir -p /mnt/backups/user/current/$1
/usr/bin/rsync -qrlHptS --delete-after \
   /home/user/$1 /mnt/backups/user/current/$1
\end{verbatim}

%%%файл backup0.sh
\begin{verbatim}
#!/bin/sh

SYNC=/home/user/homesync.sh

$SYNC cvsroot
$SYNC mail
$SYNC downloads
$SYNC archive
$SYNC work
\end{verbatim}

 Естественно, синхронизация должна происходить регулярно. Выберем период в 1
час, и составим соответствующую запись в файл 
{\tt /home/user/crontab-backups}:
\begin{verbatim}
# run 1st backup sequence every hour
0 * * * *   /home/user/backup0.sh > /dev/null 2>&1
\end{verbatim}

 Теперь будем делать накопление инкрементальных архивов на основании
полученного зеркала. Пока не будем затрагивать содержимое архивов mail,
downloads и work --- ограничимся cvsroot и archive.
Для простоты не будем предпринимать никаких
усилий по удалению пустых архивов.

%%% файл mkincremental0.sh
\begin{verbatim}
#!/bin/sh

BASE=/mnt/backups/user/
ILOGS=$BASE/ilogs/
ITARS=$BASE/itars/
BTARS=$BASE/btars/

BASENAME=$1--`date +%Y-%m-%d-%s`
TARNAME=$BASENAME.tar
LOGNAME=$BASENAME.log
LOG0NAME=$1--current

cp $ILOGS/$LOG0NAME $ILOGS/$LOGNAME

tar --listed-incremental=$ILOGS/$LOGNAME -cjf $ITARS/$TARNAME.bz2 \
        $BASE/current/$1/

rm -f $ILOGS/$LOG0NAME
cp $ILOGS/$LOGNAME $ILOGS/$LOG0NAME
\end{verbatim}

 Скрипт, который создаст нам первоначальную структуру инкрементальных
архивов:

%%% файл initincremental0.sh
\begin{verbatim}
#!/bin/sh

BASE=/mnt/backups/user/
ILOGS=$BASE/ilogs/
ITARS=$BASE/itars/
BTARS=$BASE/btars/

rm -f $ILOGS/$1-initial.log
rm -f $BTARS/$1-base.tar.bz2

tar --listed-incremental=$ILOGS/$1-initial.log \
       -cjf $BTARS/$1-base.tar.bz2 \
       $BASE/current/$1/

cp $ILOGS/$1-initial.log $ILOGS/$1--current

\end{verbatim}

 Соответствено, перед тем, как начать (уже должно существовать зеркало), мы
вызываем один раз следующий скрипт (который потом потребуется и при
ротациях).

%%% файл inittars.sh
\begin{verbatim}
#!/bin/sh

BASE=/mnt/backups/user/
ILOGS=$BASE/ilogs/
ITARS=$BASE/itars/
BTARS=$BASE/btars/

rm -Rf $ILOGS $ITARS $BTARS
mkdir -p $ILOGS $ITARS $BTARS

INIT=/home/user/initincremental0.sh

$INIT cvsroot
$INIT archive
\end{verbatim}

 Теперь приступим к заполнению болванок CDRW.

%%% Файл prepareiso.sh
\begin{verbatim}
#!/bin/sh

BASE=/mnt/backups/user/
ILOGS=$BASE/ilogs/
ITARS=$BASE/itars/
BTARS=$BASE/btars/
CDCON=$BASE/cdcon/
CD=$BASE/newcd/
VOLUME=`cat $CDCON/nextvol`
SSN=`cat $CDCON/session`
OUT=$CD/vol$VOLUME
mkdir -p $OUT/btars/
mkdir -p $OUT/itars/
mkdir -p $OUT/ilogs/
mv $BTARS/*.tar* $OUT/btars/
mv $ITARS/*.tar* $OUT/itars/
mv $ILOGS/*.log $OUT/ilogs/
bzip2 $OUT/ilogs/*.log
mkisofs -r -M $CDCON/backup.iso -o $CD/nextsession.iso $OUT
rm -Rf $OUT
\end{verbatim}

