Организация резервного копирования файлов


Зачем это нужно?

Необходимость резервного копирования начинаешь понимать только после того, как очень нужный отчёт или база данных внезапно исчезли или оказались испорченными. Цена такой потери у каждого своя, но то, что архивировать данные необходимо, становится после такой потери очевидным и бесспорным для любого руководителя.

В компьютерной сети любой компании есть несколько видов данных, подлежащих архивированию, и каждый из них архивируется по-своему. В общем случае необходимо архивировать данные серверов, отвечающих за работу AD, DNS, DHCP и т.п., базы данных SQL-серверов, пользовательские файлы и DBF-базы. Сюда же можно отнести и создание образов загрузочных дисков. У современных программных серверов для всего этого есть встроенные инструменты, они более-менее унифицированы, удобны и устраивают практически всех, хотя способы их реализации и запуска отличаются. Если кто-то хочет узнать об этом подробнее, пусть поищет в Интернете информацию по ключевым словам "теневое копирование", "NTBackup", "создание образа диска" и "SQL скрипты для архивирования". В данной статье я расскажу о быстром и дешёвом варианте архивирования пользовательских файлов и DBF-баз данных.


Немного теории

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

Какие бывают виды резервного копирования?

  • Полное резервное копирование. Архивируются все выбранные файлы. Каждый последующий архив не зависит от предыдущего.
  • Инкрементное резервное копирование. В первый раз выполняется полное резервное копирование. В последующие разы архивируются только новые файлы и изменения в файлах со времени последнего копирования.
  • Дифференциальное резервное копирование. В первый раз выполняется полное резервное копирование. В последующие разы архивируются только новые и изменённые файлы со времени последнего полного резервного копирования.

С полным копированием всё ясно: в архив попадают все выбранные файлы. Если делать каждый день полное копирование, всегда из конкретного архива можно восстановить актуальный на конкретную дату файл или каталог. Удобно для быстрого восстановления, но очень неэкономно с точки зрения дискового пространства и времени архивирования. Если у вас небольшой объём архивируемых данных и нет дефицита дискового пространства для хранения архивов, то для сисадмина и бизнеса это идеальный вариант - любой файл, каталог, база восстановятся за считанные минуты.

Инкрементное копирование - самое экономичное по времени архивирования и дисковому пространству, но восстановление одного часто изменяемого файла может привести сисадмина в состояние тихого помешательства, т.к. для этого надо последовательно откатить все варианты изменения файла со всех архивных копий. А если таких файлов 10, или 100? И если промежуточные архивы хранятся на разных носителях... При этом, если повреждён хоть один промежуточный архив, восстановить файл не удастся. Надёжность такого вида копирования самая низкая. Вывод: хотите восстановить что-то быстро и без проблем - не используйте этот метод, ибо время и данные - деньги.

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


Мои требования к резервному копированию данных

Что требовал я от программы резервного копирования и от созданного ею архива?

  • Чтобы архив создавался быстро.
  • Чтобы программа правильно работала с кириллическими именами.
  • Чтобы в одном архиве хранились данные с разных каталогов и серверов.
  • Чтобы созданный архив был формата RAR, ZIP или 7z.
  • Чтобы можно было быстро найти архив за нужную дату.
  • Чтобы в архиве можно было легко найти нужные данные.
  • Чтобы найденные данные можно было быстро и просто восстановить в нужное место.

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

Передо мной стояла задача организовать резервное копирование различного типа данных, расположенных на нескольких серверах, различных логических дисках и каталогах, используя минимальный бюджет и с учётом указанных выше требований. При этом копирование должно было длиться не более 12 часов. У меня уже работала старенькая программа BackUp32 образца 2001 года, но в связи с увеличившимся за годы объёмом данных она уже не успевала отработать от окончания одного и до начала следующего рабочего дня. Общий объём заархивированных данных составлял около 50 Гб. Можете представить, сколько требовалось места для хранения ежедневных полных архивов.

В качестве программы для архивирования я решил использовать архиватор WinRAR, точнее, его консольную версию rar.exe. Плюсы этого архиватора - огромное количество параметров командной строки, наличие 64-разрядной версии, умение работать с многоядерными процессорами, высокая скорость создания архива при высокой степени сжатия данных. И стоит это чудо всего 29 у.е. за одну лицензию (www.win-rar.ru/shop/index.php?prod=winrar)!


Практическая реализация

Была выбрана следующая схема работы с резервными копиями данных:

  • Для баз данных "1С" выполняется полное резервное копирование, чтобы не терять время на их последовательное восстановление, поскольку цена простоя достаточно высока. Период архивирования - 10 рабочих дней. Для каждого архива создаётся свой каталог хранения.
  • Для пользовательских файлов выполняется дифференциальное резервное копирование. Период архивирования - 10 рабочих дней. Для каждого архива создаётся свой каталог хранения.
  • Задача реализуется на bat-файлах, работа которых документируется в логах. Файлы логов находятся в дочернем каталоге \logs.
  • Скрипт запускается на самом мощном сервере. В моём случае это вполне приличный сервер HP с двумя четырёхъядерными Xeon'ами по 2.8 ГГц, RAM 18Гб, Windows Server 2008 R2 Standard х64.
  • Каждый архив вначале создаётся во временном каталоге сервера-архиватора. Затем архив автоматически переносится на удалённый сервер для хранения. Опытным путём я установил, что такая схема работы с данными - самая быстрая. Все серверы соединены между собой по гигабитной сети, поэтому копирование происходит быстро. Например, архив в 14 Гб копируется за 4 минуты.
  • Начало копирования - не ранее чем через час после окончания рабочего дня.
  • Каждый архив имеет имя, состоящее из тематического наименования и даты начала создания архива в формате YYMMDD. Например, архив диска Х за 12 января 2011 года: Disk_Х110112.rar.
  • Если архивов в каталоге более 10, самый старый архив автоматически удаляется.
  • Каждый месяц архивы вручную переносятся на независимый носитель информации на долгосрочное хранение сроком на 1 год.


Исходные тексты bat-файлов

Вся работа выполняется с помощью трёх видов командных файлов:

  • Файлы для создания полных архивов.
  • Файлы для создания дифференциальных архивов.
  • Файл для запуска всех указанных выше файлов. Именно он и запускается планировщиком задач Windows.

Что означают применённые ниже опции архиватора, можно прочитать в текстовом файле помощи rar.txt, который идёт вместе с дистрибутивом WinRAR. В этом файле более 2000 строк, поэтому я рекомендую прочитать его самостоятельно. Тот, кто прочитает файл помощи, найдёт для себя ещё много полезного и, возможно, применит это в своей практике или изменит мои скрипты для своих нужд.

Итак, сами командные файлы.

Архивирование баз данных "1С" выполняется методом полного резервного копирования bat-файлом, текст которого приведён в листинге 1.

Листинг 1

rem - файл Disk1_1C.bat -
rem Создание переменных. Записываются в переменные
rem дата и время начала копирования, имя файла лога
rem для этого файла, имя файла лога для архиватора,
rem имя архива, путь для хранения архива
SET StartD=%date%
SET StartT=%time%
SET FName=logs\log1_1C.txt
SET ErrName=logs\Err1_1C.txt
SET ArcName=Disk1_1C
SET ToStore=\\ServerBak\DiskBak$\Backups\Disk1_1C\Disk1_1C
rem Начало работы скрипта - запись в лог bat-файла
ECHO -- %StartD% -- >> %FName%
ECHO Start %ArcName% at %StartT% >> %FName%
rem Само архивирование
Start /wait rar u -ilog%ErrName% -ep2 -m5 -inul -r -ri15 -dh -msjpg;pdf;cdr -wd:\temp -scal -x@exclude.txt -agYYMMDD %ToStore% @incl1_1C.txt
rem Обработка ошибок по кодам возврата с записью в лог bat-файла
IF ERRORLEVEL=255 (
ECHO 255 Операция была прервана пользователем >> %FName%
GOTO End1
)
IF ERRORLEVEL=9 (
ECHO 9 Произошла ошибка при создании файла >> %FName%
GOTO End1
)
IF ERRORLEVEL=8 (
ECHO 8 Недостаточно памяти для выполнения операции >> %FName%
GOTO End1
)
IF ERRORLEVEL=7 (
ECHO 7 Допущена ошибка при указании команды/параметра в командной строке >> %FName%
GOTO End1
)
IF ERRORLEVEL=6 (
ECHO 6 Произошла ошибка открытия файла >> %FName%
GOTO End1
)
IF ERRORLEVEL=5 (
ECHO 5 Произошла ошибка записи на диск >> %FName%
GOTO End1
)
IF ERRORLEVEL=4 (
ECHO 4 Предпринята попытка изменить архив, ранее заблокированный командой 'k' или ключом '-k' >> %FName%
GOTO End1
)
IF ERRORLEVEL=3 (
ECHO 3 Во время распаковки обнаружена ошибка CRC >> %FName%
GOTO End1
)
IF ERRORLEVEL=2 (
ECHO 2 Произошла критическая ошибка >> %FName%
GOTO End1
)
IF ERRORLEVEL=1 (
ECHO 1 Произошла некритическая ошибка >> %FName%
GOTO End1
)
IF ERRORLEVEL=0 (
ECHO 0 Работа завершена без ошибок >> %FName%
GOTO End1
)
:End1
rem Удаление самого старого 11-го файла
for /f "skip=10 delims=:" %%i in ('dir \\ServerBak\DiskBak$\Backups\Disk1_1C\*.* /O-D /b') do del /q "\\ServerBak\DiskBak$\Backups\Disk1_1C\%%i"
rem Конец работы скрипта - запись в лог bat-файла
SET EndT=%time%
ECHO End %ArcName% at %EndT% >> %FName%

Как видно из Скрипта 1, в каталоге всегда находится не более 10 архивов, независимо от их даты создания (число "10" в строке определяет их количество). Если же необходимо, чтобы в каталоге были архивы за последние 10 календарных дней, независимо от их количества, т.е. независимо от того, сколько раз в день производится архивирование, то можно использовать vbs-скрипт. Для этого строка

for /f "skip=10 delims=:" %%i in ('dir \\ServerBak\DiskBak$\Backups\Disk1_1C\*.* /O-D /b') do del /q "\\ServerBak\DiskBak$\Backups\Disk1_1C\%%i"

заменяется вот такой строкой (имя каталога передаётся через аргумент ArcPath):

start /wait DelArcs.vbs /ArcPath:\\ServerBak\DiskBak$\Backups\Disk1_1C\

Разумеется, при этом в имя архива нужно включить, например, время создания архива, чтобы имена архивов в течение одного дня оставались уникальными. Сам vbs-скрипт приведён в листинге 2. Он должен находиться в том же каталоге, что rar.exe.

Листинг 2

'- Начало файла DelArcs.vbs -
Dim objNamedArgs
Set objNamedArgs= WScript.Arguments.Named
If objNamedArgs.Exists("ArcPath") Then
Set filesys = CreateObject("Scripting.FileSystemObject")
Set objFolder = filesys.GetFolder(objNamedArgs("ArcPath"))
For Each File in objFolder.Files
If DateDiff("D", File.DateLastModified, Now) > 10 Then
File.Delete true
End If
Next
Else
WScript.Echo ("Отсутствует аргумент ArcPath")
End If

В результате работы Скрипта 1 создаётся примерно такой файл лога (я специально добавил варианты с ошибками):

- 25.01.2011 -
Start Disk1_1C at 19:30:00,42
0 Работа завершена без ошибок
End Disk1_1С at 19:39:30,43

- 26.01.2011 -
Start Disk1_1С at 13:14:30,71
255 Операция была прервана пользователем
End Disk1_1C at 13:14:36,55

- 27.01.2011 -
Start Disk1_1С at 19:52:47,23
6 Произошла ошибка открытия файла
End Disk1_1C at 20:05:52,12

Если в процессе работы rar.exe происходят ошибки, он записывает их в собственный лог, например:

- 11 Jan 2011, archive K:\Backups\Disk1_1C\Disk1_1C110111.rar
20:00:20 Cannot open Z:\Server_SQL\usrdef\users\Иванов\1Cv7.LCK
20:00:20 Не удаётся найти указанный файл.

Архивирование пользовательских файлов выполняется методом дифференциального резервного копирования bat-файлом, текст которого приведён в листинге 3.

Листинг 3

rem - Начало файла Disk1_Users1.bat -
rem Создание переменных. Записываются в переменные дата
rem и время начала копирования, имя файла лога для этого
rem файла, имя файла лога для архиватора, имя архива, путь
rem для хранения архива
SET StartD=%date%
SET StartT=%time%
SET FName=logs\log_Users1.txt
SET ErrName=logs\Err_Users1.txt
SET ArcName=Disk1_Users1
SET ToStore=\\ServerBak\DiskBak$\Backups\Disk1_Users1
rem Начало работы скрипта - запись в лог bat-файла
ECHO -- %StartD% -- >> %FName%
ECHO Start %ArcName% at %StartT% >> %FName%
rem Само архивирование
Start /wait rar u -ilog%ErrName% -ep2 -m5 -inul -r -ri15 -dh -msjpg;pdf;cdr -ver10 -wd:\temp -scal -x@exclude.txt %ToStore% @incl1_Users1.txt
rem Обработка ошибок и запись в лог bat-файла
IF ERRORLEVEL=255 (
ECHO 255 Операция была прервана пользователем >> %FName%
GOTO End1
)
IF ERRORLEVEL=9 (
ECHO 9 Произошла ошибка при создании файла >> %FName%
GOTO End1
)
IF ERRORLEVEL=8 (
ECHO 8 Недостаточно памяти для выполнения операции >> %FName%
GOTO End1
)
IF ERRORLEVEL=7 (
ECHO 7 Допущена ошибка при указании команды/параметра в командной строке >> %FName%
GOTO End1
)
IF ERRORLEVEL=6 (
ECHO 6 Произошла ошибка открытия файла >> %FName%
GOTO End1
)
IF ERRORLEVEL=5 (
ECHO 5 Произошла ошибка записи на диск >> %FName%
GOTO End1
)
IF ERRORLEVEL=4 (
ECHO 4 Предпринята попытка изменить архив, ранее заблокированный командой 'k' или ключом '-k' >> %FName%
GOTO End1
)
IF ERRORLEVEL=3 (
ECHO 3 Во время распаковки обнаружена ошибка CRC >> %FName%
GOTO End1
)
IF ERRORLEVEL=2 (
ECHO 2 Произошла критическая ошибка >> %FName%
GOTO End1
)
IF ERRORLEVEL=1 (
ECHO 1 Произошла некритическая ошибка >> %FName%
GOTO End1
)
IF ERRORLEVEL=0 (
ECHO 0 Работа завершена без ошибок >> %FName%
GOTO End1
)
:End1
rem Конец работы скрипта - запись в лог bat-файла
SET EndT=%time%
ECHO End %ArcName% at %EndT% >> %FName%

Файлы логов аналогичны вышеприведённым.

Как видно из Скриптов 1 и 3, для работы rar.exe необходимо наличие двух текстовых файлов, в которых указывается, что архивировать, а что - не архивировать. Что не архивировать, включено в один общий для всех файл exclude.txt. Вот он в усечённом виде. Каждый сам определит, что ему не нужно архивировать.

  • *.cdx
  • *.rar
  • *.mov
  • *.avi
  • *.zip
  • Thumbs.db

Файлы и каталоги, которые необходимо архивировать, помещены в другой текстовый файл, для каждого архива свой. Например, так может выглядеть файл incl1_1C.txt:

\\Server1\1C$\NETHASP.INI
\\Server1\1C$\Nhsrv.ini
\\Server2\1C$\Base1\*.*
\\Server2\1C$\Tax2\*.*
\\Server3\HomeUsers$\*
\\Server4\1C$\NETHASP.INI
\\Server4\1C$\Nhsrv.ini

При разумном наименовании текстовых файлов находить и сопровождать их очень легко, редактируя, добавляя или удаляя строки.

Все командные файлы запускаются по очереди одним, главным, командным файлом. Он выглядит так (см. листинг 4).

Листинг 4

rem - Начало файла AllBak.bat -
rem Выполняется переход в каталог программ архивирования
CD /d D:\Arcs
rem Создание переменных. Записываются в переменные дата и
rem время начала всего процесса копирования, имя файла лога
rem для этого файла
SET StartD=%date%
SET StartT=%time%
SET FName=logs\log_All.txt
rem Начало работы - запись в лог главного bat-файла
ECHO -- %StartD% -- >> %FName%
ECHO Start BackUp at %StartT% >> %FName%
rem Последовательный вызов и выполнение bat-файлов архивирования
Call Disk1_1C.bat
Call Disk2_1C.bat
Call Disk3_1C.bat
Call Disk_User1.bat
Call Disk_User2.bat
rem Конец работы - запись в лог главного bat-файла
SET EndT=%time%
SET FName=logs\log_All.txt
ECHO End BackUp at %EndT% >> %FName%

В результате работы Скрипта 4 получаем лог длительности всего процесса архивирования. Он полезен для контроля и отладки и выглядит примерно так:

-- 21.01.2011 --
Start BackUp at 19:30:00,30
End BackUp at 1:30:10,86

-- 24.01.2011 --
Start BackUp at 19:30:00,20
End BackUp at 22:13:22,76

-- 25.01.2011 --
Start BackUp at 19:30:00,40
End BackUp at 22:27:05,92

Главный командный файл запускается планировщиком задач сервера. В свойствах задания необходимо отметить "Выполнять вне зависимости от регистрации пользователя". В этом случае скрипт отработает при включённом сервере, без входа пользователя. Обратите внимание, что птичка "Останавливать при переходе на питание от батарей", должна быть снята, иначе при нестабильной электрической сети задание будет всё время сниматься! И ещё. Поскольку скрипт работает без входа пользователя на сервер, все сетевые пути необходимо указывать не через логические имена (буквы), а именно так, как у меня в скриптах.


Как восстанавливать архивы

Очень просто! В любом файловом менеджере открываем архив как каталог. Если у вас установлен архиватор 7Zip, то RAR-архив можно открыть в Проводнике Windows. Total Commander и FAR не требуют установки архиваторов для работы с rar-архивами. Итак, открыли архив, что дальше? Для полных архивов всё очевидно, на то он и полный архив. В дифференциальных архивах есть одна особенность. В отличие от обычных программ резервного копирования, архиватор RAR все версии одного файла хранит в одном архиве, и это на самом деле здорово. Количество версий задаётся при архивировании параметром ver. При обновлении файлов в уже существующем архиве предыдущие версии переименовываются в 'filename;n', где 'n' - номер версии. Например, файл Notes.doc - последняя (например, вчерашняя) версия. Самая первая (самая старая) версия будет называться Notes.doc;1. Таким образом, в одном архиве в одном месте хранятся все версии файла, можно выбрать версию за нужную дату и восстановить в любое место простым копированием. Согласитесь, это удобнее, чем искать в разных архивах и смотреть, изменялся нужный файл в этот день или нет. Пользователь это, естественно, забыл, но ему очень нужно.


Итог

После замены ранее используемой программы BackUp32 на мои скрипты процесс архивирования вместо 15 часов стал занимать 3 часа! При этом используемое место на архивном диске уменьшилось наполовину из-за применения дифференциальных архивов, и я смог увеличить период оперативного архивирования. Согласитесь, ради всего этого стоило поработать.

Александр РЫКУНИН

Версия для печатиВерсия для печати

Номер: 

09 за 2011 год

Рубрика: 

На заметку
Заметили ошибку? Выделите ее мышкой и нажмите Ctrl+Enter!

Комментарии

Страницы

Аватар пользователя Al
2 Savely. Да, верно! Это у меня осталось от отладки и изучения параметров команды. А по древнему правилу программистов, если оно работает, то не надо и трогать! ))) Вообще, конечно, достаточно вот такой строки: for /f "skip=10" %%i in ('dir D:\Test\*.* /O-D /b') do del /q "D:\Test\%%i" и так же всё будет работать. Т.е. принцип - обратная сортировка в папке и удаление верхнего самого старого файла, пока не останется 10.

Спасибо за указание ошибки, точнее, избыточности!

Аватар пользователя Savely
>Да, верно!

От души отлегло :)) FOR /F - таки все же довольно "темная" штука... Но мощная и очень полезная.

Аватар пользователя Savely
P.S. Al - ты забыл ARом прикинуться, когда мне отвечал :))

Страницы