«Береженного бог бережет» (или backup «подручными» средствами)

«Ничего вечного нет!» Хорошие слова. Плохо лишь то, что вспоминаем мы их обычно уже после того, как «сервер лёг». Пока мой «домашний сервер» был просто игрушкой, вспоминать про слово «backup» я и не собирался. Но постепенно моя «игрушка» выросла до полезной в хозяйстве штуки… Которую стало жалко терять… И даже более того — которую в случае чего нужно было бы срочно «поднимать» (восстанавливать). А чтобы было из чего восстанавливать, что нужно? Точно — резервная копия или «backup» (если на «родном» английском)!

Что такое «резервная копия»? Это (а) копия критичных данных, и главное — (б) сделанная ещё с работающей системы! Наверняка существуют множество самых разных уже готовых программ, выполняющих резервное копирование. Все они делают одно и то же — по «какому-то» расписанию «куда-то» копируют эти самые «важные» данные. Зачастую при этом используются методы архивации (сжатия) копируемых данных с целью экономии места, занимаемого резервной копией. И над всем этим присутствует какой-то фронт-энд (зачастую графический) для настройки и управления.

А так ли уж нужен GUI, тем более для случая сервера под управлением Linux? В былые времена я и в Windows вполне прекрасно обходился простым bat-файлом, запускаемым по расписанию. Вот и в этом случае решил сделать нечто подобное. Правда, было еще одно обстоятельство, с решением которого я ранее не сталкивался. Речь идет о необходимости резервного копирования информации из базы данных MySQL. А потребность эта вызвана тем, что многие современные сайты построены на т.н. системах управления содержимым (CMS), которые в своей работе используют базу данных MySQL. Примером такой системы вполне может являться WordPress, использованный мной для ведения данного блога. И значительная часть его информации хранится именно в базе данных MySQL. Следовательно, базу эту нужно «резервно копировать» пренепременно. Осталось лишь найти способ…

И средство нашлось! Для управления своим «сервером» я (среди прочего) уже давно использую Webmin. Что это такое? Это мощный инструмент управления компьютером, работающим под управлением Linux. Причем, (а) инструмент с веб-интерфейсом, и (б), позволяющий управлять компьютером дистанционно. Запустите любой нравящийся Вам браузер и введите в поле адреса:

https://имя_вашего_компьютера:10000

Естественно, вместо «имя_вашего_компьютера» Вы должны ввести сетевое имя Вашего компьютера, например, «https://printserver:10000» (а можно и просто его сетевой адрес, например, «https://192.168.1.1:10000«). Вариантов реакции на такую команду может быть несколько. Первый — самый успешный: появится окно в котором Вас попросят ввести имя пользователя и пароль. Пользователь изначально всего один — root (администратор), ну а пароль его для Вашего компьютера должны знать Вы, а не я. Вариант второй — сообщение об ошибке (неверном запросе) и предложение перейти по ссылке вида «http://имя_вашего_компьютера:10000«. Просто жмете по предложенной ссылке, и далее как в первом случае — имя, пароль… Но возможен и третий вариант — самый «грустный»: сообщение браузера о том, что «попытка соединения не удалась». Это значит, что Webmin на Вашем компьютере не установлен. Плохо! Но не смертельно. Запускаем консоль от имени администратора (root) и вводим команду

urpmi webmin

Немного ждем. Получив сообщение о том, что установка программы завершена, повторяем попытку с браузером. В этот раз все должно быть хорошо. Вводим имя (root), пароль — и вот мы уже можем «рулить». Работу в Webmin я порекомендовал бы начать с выбора языка. Для этого в верхней строке меню жмем на пункт «Webmin«, затам выбираем ярлык (иконку) «Webmin Configuration«, а в открывшемся списке — пункт «Language«. Выбираем «по вкусу» язык из списка, и жмем кнопку «Change Language«… И пару слов о «дистанционности». Если в файерволе Вашего компьютера открыть доступ по порту 10000, то с помощью Webmin Вы сможете управлять им дистанционно (с других компьютеров в сети).

Кстати, а не пора ли нам вернуться к резервному копированию? А именно, к сохранению информации из базы данных MySQL. В верхнем меню выбираем пункт «Службы«. В списке служб выбираем «Сервер баз данных MySQL«. В нижней части открывшейся страницы будет кнопка «Backup Databases» (см. рис. ниже).

Включение автоматического резервного копирования баз MySQL
Включение автоматического резервного копирования баз MySQL

Вот именно на эту кнопку и жмем! Откроется страница, которая называется «Backup All Databases». Единственное горе — даже при выбранном русском языке интерфейса Webmin она все равно отображается на английском (не переведена). Главные интересующие нас поля — «Backup destination» (назначение) и » Backup schedule» (расписание). «Назначение» — это папка, в которую будет записываться резервная копия. Я решил, что из соображений безопасности эту папку следует разместить в личной папке администратора (не доступной для остальных). Поэтому, я ввел значение /root/mysql_backup (не мудрствуя лукаво). Смысл же «расписания», думаю, и так понятен — когда (часы/минуты/дни/ и т.д.) должно АВТОМАТИЧЕСКИ (т.е. самостоятельно) выполняться резервное копирование баз данных MySQL. Как часто Вы захотите выполнять резервное копирование — дело сугубо личное Ваше и Вашей паранойи. Определившись с графиком, вводите требующиеся значения в поля расписания, после чего жмете кнопку «Save» (сохранить) в самом низу страницы. Всё! Теперь Ваш компьютер в указанное время будет автоматически делать экспорт всех данных из всех баз MySQL в указанную папку. Первая часть задачи решена…

Теперь перейдем непосредственно к … резервному копированию. «Как перейдем? А до этого чем занимались?» — спросите Вы. «До этого» мы занимались (а) поиском/установкой программы Webmin и (б) экспортом данных из баз MySQL. Теперь же мы начинаем сохранять важные для нас файлы и папки. Какие — решать Вам. Одну важную папку с файлами могу Вам подсказать и я — это папка /root/mysql_backup, в которую мы только что (выше) экспортировали все данные из всех баз MySQL. Как сохранять? Конечно, лучше с архивацией (сжатием), чтобы экономить место. На мой взгляд, для этого вполне подходит какая-нибудь программа-архиватор, которой указывается источник — папка с данными, и архив-приемник. Лично я выбрал архиватор zip. Одиночная команда (внимание, это ОДНА строка!!!) выглядит (например) так:

zip -r -u -y /root/backup/html /var/www/html/* -x *.exe >> /var/log/all_backup.log

По этой команде:

  • программа zip
  • обновляет (ключ -u)…
  • архив /root/backup/html (расширение «.zip» программа выходному файлу добавит сама)…
  • всеми файлами (симавол звездочки — *)…
  • из папки /var/www/html/
  • включая все вложенные подпапки (ключ -r)…
  • за исключением т.н. «жестких ссылок» (симлинков) (ключ -y)…
  • и за исключением файлов с расширением «exe» (ключ -x *.exe).
  • При этом все сообщения программы zip перенаправляются в файл протокола (параметр >> /var/log/all_backup.log)

Обычно на компьютере присутствует далеко не одна такая «важная папка». По этому, есть смысл последовательно, шаг за шагом, сделать резервные копии (архивы) каждой из них. То есть, выполнить определенную последовательность команд. Как я упоминал в самом начале, в DOS, а в последствии и в Windows, была возможность создавать специальные файлы, в которых перечислялась последовательность команд. При запуске таких файлов перечисленные в них команды выполнялись последовательно одна за другой. Это были т.н. bat-файлы. В Linux также имеются аналогичные файлы, называемые скриптами. Название иное, но суть та же.

То есть, чтобы сделать резервные копии нескольких «важных» папок, напишем скрипт, в котором последовательно перечисляем команды, аналогичные приведенной выше, естественно, изменив имена исходных данных и выходных архивов. Создадим новый файл, назовем его, например, backup.sh и впишем в него команды архивирования. Выглядеть это может, например, вот так:

#! /bin/bash
date -R > /var/log/all_backup.log
zip -r -u -y /root/backup/etc /etc/* >> /var/log/all_backup.log
zip -r -u /root/backup/html /var/www/html/* -x *.exe >> /var/log/all_backup.log
zip -r -u /root/backup/alfresco /opt/Alfresco/* >> /var/log/all_backup.log
zip -r -u /root/backup/mysql /root/mysql_backup/* >> /var/log/all_backup.log

Кое-что в приведенном выше фрагменте, думаю, нуждается в пояснениях. Первая строка — #! /bin/bash — является комментарием. В ней указано, какой командный интерпретатор будет использоваться при выполнении команд, перечисленных в скрипте. Вторая сторка — date -R > /var/log/all_backup.log — элемент ведения лога (протокола работы). Поподробнее. Лично мне очень нравится протоколирование работы компьютера, реализованное в Linux-системах. Если знаешь, что и где посмотреть, то прочесть можно очень многое. Поэтому, решил я, и мое резервное копирование тоже должно вести свой лог. При этом, я решил использовать для своего процесса «персональный» файл лога — /var/log/all_backup.log. Команда «date -R«, (во второй строке скрипта) просто выводит дату в формате вида «Thu, 06 Nov 2008 15:45:01 +0200», а стрелка «>» перенаправляет этот вывод вместо консоли в указанный файл лога. Затем в скрипте идут четыре команды про архивирование различных папок с моего компьютера, которые я для себя посчитал критически важными. Реальное количество строк, а также имена папок, важных для Вас, Вы можете выбрать и указать самостоятельно. В каждой (с 3-й по 6-ю) строке, содержащей команду про архивирование, сообщения архиватора также перенаправляются в файл лога. Единственное, наблюдается отличие в числе «перенаправляющих» стрелок — их там по две. Что это дает? Если стрелка одна, то сообщение записывается в «чистый» файл. При этом, если файл был не пуст, то его старое содержимое стирается. Если же стрелок в команде две, то новые данные (сообщения) будут дописываться в конец указанного файла, сохраняя его старое содержимое. Таким образом, при запуске моего скрипта старый лог стирается, и первой строкой в новый лог записывается дата выполнения резервного копирования. По мере выполнения команд в него добавляются строки с сообщениями архиватора (вида «updating: etc/vmware/vmnet8/dhcpd/dhcpd.leases (deflated 59%)«, причем «немерянное» их количество)…

Итог работы той части скрипта, которую я привел выше — четыре (в моем случае) архивных файла, расположенных в папке /root/backup. В определенной степени это уже резервная копия. А с учетом того, что она находится в папке администратора (root), то это еще и копия, защищенная от других (менее привилегированных) пользователей. Однако, она расположена на том же самом винчестере того же cамого компьютера. Ах, если бы винчестеры был вечными! Тогда мы смело могли бы утверждать, что наша задача выполнена! Но, увы… На самом деле, пока что мы можем лишь рапортовать о выполнении второго этапа нашей задачи. Что дальше?

Чтобы почувствовать себя гораздо более защищенным, наши резервные копии настоятельно рекомендуется скопировать еще куда-то. Куда? Можно на другой компьютер. Причем, как в локальной сети, так и в глобальной. Можно на другой носитель. Например, на флешку. Вот лично я решил копировать на DVD+RW диск. Болванка (перезаписываемая) стоит примерно 1 доллар, привод соответствующий в моем «сервере» уже имеется, так чего ж тогда ему зря простаивать-то?…

Скажу честно, до этого я еще никогда не писал диски с консоли (в режиме «голой» командной строки). Как-то все больше при помощи программ с графическим интерфейсом — той же «Nero», например, или еще чем-то подобным. А вот кто будет мышь по рабочему столу «тягать», если наше резервное копирование — автоматическое? Как запустить из консоли запись? Поискал, оказывается, нет ничего невозможного — есть такая возможность в Linux. Кто знает, может быть и в Windows нынче тоже можно записать диск из командной строки, но у меня просто не возникало такой необходимости. А тут вот «приперло». Итак, для начала проверим, есть ли у нас все необходимое. Введем в консоли от имени администратора (root) пару команд (вводимые мной команды выделены красным цветом, ответы системы — нет):


[root@my-svr ~]# urpmi cdrkit
Пакет cdrkit-1.1.6-5mdv2008.0.i586 уже установлен
[root@my-svr ~]# urpmi dvd+rw-tools
Пакет dvd+rw-tools-7.0-3mdv2008.0.i586 уже установлен

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

  • Стираем старый подготовленныый образ диска;
  • Программой mkisofs создаем новый образ диска;
  • Программой dvd+rw-format форматируем диск DVD+RW;
  • Программой growisofs записываем образ на DVD+RW диск.

«Направление движения задано», продолжаем писать скрипт. Добавляем в него следующие три команды:

/bin/rm /root/temp.iso
ls -l /root/backup >> /root/backup/files_list.txt
VOL=`date +%d-%m-%Y_%H:%M`

Первая из них стирает старый файл образа диска (temp.iso). Вторая команда создает текстовый файл files_list.txt со списком всех файлов (архивов), находящихся в папке /root/backup. По сути, это перечень тех архивов (резервных копий), которые мы создали ранее и теперь запишем на диск. Третья команда задает (описывает) переменную «VOL». Что она нам дает. В дальнейшем при выполнении скрипта вместо переменной будет подставляться ее значение. Забегая вперед скажу, что данная переменная будет использоваться при создании диска в качестве его имени тома. А согласно присвоенного нами значения, вместо нее будет подставляться текущее значение времени и даты в формате «дата-месяц-год_часы:минуты». То есть, именем записанного нами диска будет время выполнения резервной копии. На мой взгляд, удобно. Что дальше? Создаем образ диска. Для этого в скрипт пишем следующее:

if /usr/bin/mkisofs -o /root/temp.iso -J -r -V ${VOL} /root/backup &> /var/log/disk_write.log
then echo "ISO file maked OK!" >> /var/log/all_backup.log
else echo "Error iso file creation!!!" >> /var/log/all_backup.log
fi

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

/usr/bin/mkisofs -o /root/temp.iso -J -r -V ${VOL} /root/backup &> /var/log/disk_write.log

По этой команде:

  • программа mkisofs;
  • создает образ диска — файл /root/temp.iso;
  • с именем, равным значению переменной «VOL» (ключ -V ${VOL})
  • совместимого с форматом Joilet (ключ -J)
  • также совместимого с форматом Rock Ridge (ключ -r)
  • используя в качестве источника файлы, расположенные в папке /root/backup;
  • Также, вывод сообщений программы перенаправлен в файл /var/log/disk_write.log

Результатом работы программы будет файл образа диска temp.iso, расположенный в папке /root. Вся остальная конструкция, накрученная вокруг команды обеспечивает запись в лог файл сообщения «ISO file maked OK!», если работа программы завершилась успешно, или же сообщения «Error iso file creation!!!», если в работе программы произошла ошибка.

Образ создан. Пора форматировать диск. Снова целая конструкция:

if /usr/bin/dvd+rw-format -force /dev/dvd &> /var/log/disk_write.log
then echo "Disk formated OK!" >> /var/log/all_backup.log
else echo "Disk format error!!!" >> /var/log/all_backup.log
fi

По результатам выполнения команды в лог пишется либо сообщение «Disk formated OK!», либо сообщение «Disk format error!!!» для случаев удачного и неудачного завершения работы программы соответственно. Сама команда:

/usr/bin/dvd+rw-format -force /dev/dvd &> /var/log/disk_write.log

выполняет следующее:

  • программа dvd+rw-format
  • форматирует DVD-RW диск /dev/dvd
  • не взирая ни на что, т.е. в принудительном порядке (ключ -force).
  • Также, вывод сообщений программы перенаправлен в файл /var/log/disk_write.log

После того, как диск отформатирован, остается лишь записать на него созданный нами ранее образ. Займется этим следующая команда:

if /usr/bin/growisofs -use-the-force-luke=tty -dvd-compat -Z /dev/dvd=/root/temp.iso &> /var/log/disk_write.log
then echo "Disk ${VOL} was writed OK!" >> /var/log/all_backup.log
else echo "Error disk writing!!!" >> /var/log/all_backup.log
fi

При этом:

  • программа growisofs
  • в режиме совместимости с DVD-проигрывателями (ключ -dvd-compat)…
  • записывает первой сессией (ключ -Z)…
  • файл-образ /root/temp.iso
  • на диск, расположенный в приводе /dev/dvd.
  • Опция -use-the-force-luke=tty (недокументированная) подсмотрена мной на одном из форумов, как «решение возможных проблем».
  • Также, вывод сообщений программы перенаправлен в файл /var/log/disk_write.log

А остальная «конструкция условий», которой обвешана сама команда, обеспечивает запись в лог сообщения о том, было ли ее исполнение успешным («Disk ${VOL} was writed OK!»), либо неудачным («Error disk writing!!!»). При этом в сообщении об успешной записи выводится имя диска, которое, как было задано нами ранее, является датой и временем создания резервной копии.

НО! Через какое-то время команда записи образа на диск ПЕРЕСТАЛА РАБОТАТЬ! В логе при этом сообщалось о том, что «файл не найден». Данное сообщение поначалу вызвало у меня удивление — ведь файл образа диска /root/temp.iso был на своем месте!! А подвел меня в анализе сообщений об ошибке недостаток моих знаний по Linux. Не буду ходить «вокруг да около». Система на самом деле не могла найти файл ссылки на устройство /dev/dvd. Заглянул в папку /dev — там действительно не нашлось файла dvd, зато был файл dvd1. Команду я исправил соответственно:

/usr/bin/growisofs -use-the-force-luke=tty -dvd-compat -Z /dev/dvd1=/root/temp.iso &> /var/log/disk_write.log

После этого запись возобновилась…

Последней командой, которую я вписал в мой скрипт была следующая:

ls -l /root/backup >> /var/log/all_backup.log

Ее назначение чисто информативное. Команда выводит в лог список файлов, записанных на диск. Список этот аналогичен тому, что мы записали и на сам диск. Полезен тем, что позволяет нам увидеть какие файлы и с какими датами последнего изменения (читай «резервного копирования») попали в текущую резервную копию.

По ходу нашего резевного копирования мы так много всего писали в лог! Что же получилось в конечном итоге? Наш лог файл /var/log/all_backup.log по окончании работы скрипта будет содержать примерно следующее:


Thu, 06 Nov 2008 15:45:01 +0200
updating: etc/ntp/drift (stored 0%)
updating: etc/vmware/vmnet8/dhcpd/ (stored 0%)
updating: etc/vmware/vmnet8/dhcpd/dhcpd.leases (deflated 59%)
....
....
(тут мной пропущено ну очень много подобных строчек)...
....
....
updating: root/mysql_backup/wp_db.sql (deflated 91%)
ISO file maked OK!
Disk formated OK!
Disk 06-11-2008_15:46 was writed OK!
total 1940696
-rw-r--r-- 1 root root 338362715 Nov 6 08:06 alfresco.zip
-rw-r--r-- 1 root root 19181489 Nov 6 15:45 etc.zip
-rw-r--r-- 1 root root 1118 Nov 6 15:46 files_list.txt
-rw-r--r-- 1 root root 605922523 Nov 6 11:07 gallery.zip
-rw-r--r-- 1 root root 1021234092 Nov 6 15:46 html.zip
-rw-r--r-- 1 root root 593094 Nov 6 15:46 mysql.zip

Итак, архивы обновлены, образ создан, диск отформатирован и записан, содержимое прилагается! Все! Скрипт, который при его запуске делает нам резервную копию системы, мы создали! Те, кому лень набирать его руками, могут взять его в виде готового файла backup.sh с моего ftp-сервера. Единственное, что придется сделать, так это назначить ему атрибут «исполняемый» командой:

chmod +x backup.sh

После этого можно для пробы запустить его разочек с консоли. Диск только в привод не забудьте вкинуть! И до полного счастья автоматического резервного копирования нам осталось лишь назначить расписание по которому будет выполняться данная процедура. В Linux есть специальная служба, которая выполняет по расписанию самые различные задачи. Называется она «cron», и все что нам нужно сделать — вписать в нее выполнение нашего скрипта резервного копирования. А поможет нам в этом все тот же Webmin. Запускаем его. Выбираем закладку «Система», а в ней ярлык (иконку) «Расписание заданий cron», как показано на рис. ниже:

Вход в настройку cron
Вход в настройку cron

Откроется список всех уже назначенных заданий. Мы же находим ссылку «Создать новое задание» (вверху) и жмем на нее. Откроется окно создания нового задания (см. рис. ниже):

Настройка графика выполнения задания
Настройка расписания выполнения задания

В открывшемся окне указываем, что запускаться задание будет от имени администратора (root), в поле «Команда» вписываем имя нашего скрипта (лучше с полным путем), выбираем расписание (часы, минуты, дни и т.д…) по которому оно будет автоматически запускаться, и затем жмем кнопку «Создать» внизу страницы. Вот таперь уже точно все! В выбранное Вами время, в выбранные Вами дни, компьютер будет самостоятельно создавать архив выбранной Вами важной информации и записывать его на DVD-RW-диск. Хорошо!

Дополнительные ссылки, которые мне помогли:
http://ru.wikipedia.org/wiki/Growisofs
http://swaj.net/zametki/z-linux-cd_dvd_recording.html
http://www.opennet.ru/base/sys/cdmake_linux.txt.html