Pull to refresh

CMD/BAT, резервное копирование и глубина архивации

Наиболее доступный инструмент для резервного копирования — командная строка. Найти более-менее приличную реализацию резервного копирования в Windows-системах средствами CMD/BAT-файлов можно, воспользовавшись любым поисковиком. Однако часто нет необходимости накапливать и хранить все созданные архивы, достаточно лишь нескольких самых последних. В этом случае необходима реализация резервного копирования с поддержкой глубины архивации. Найти реализацию поддержки глубины архивации в таких скриптах уже гораздо сложнее.

Вашему вниманию — относительно простой скрипт (CMD-сценарий), реализующий резервное копирование с заданной глубиной архивации.

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

Содержимое скрипта:

SETLOCAL enabledelayedexpansion

rem Глубина архивации (количество последних архивов, которые должны быть сохранены)
SET ArcDepth=5

rem Путь к каталогу, в который будут складываться резервные копии
SET DirName=My Backup's
rem Путь к каталогу с новым бэкапом (%DATE: =0% %TIME: =0% - замена пробелов в %DATE% и %TIME% на нули)
FOR /f "tokens=1-7 delims=/-:., " %%a IN ("%DATE: =0% %TIME: =0%") do (
	SET NewBkDir=%DirName%\%%c.%%b.%%a_%%d.%%e.%%f.%%g
)
rem Путь к лог-файлу
SET LogFile=%DirName%\%DirName%.LOG

ECHO ***** НАЧАЛО %DATE% %TIME% ***** >> "%LogFile%"

IF NOT EXIST "%DirName%" (
	MD "%DirName%"
	ECHO "%DirName%" - создан >> "%LogFile%"
)

ECHO Создание нового каталога для бэкапа: >> "%LogFile%"
IF NOT EXIST "%NewBkDir%" (
	MD "%NewBkDir%"
	ECHO "%NewBkDir%" - создан >> "%LogFile%"
) ELSE (
	ECHO "%NewBkDir%" - существовал ранее >> "%LogFile%"
)

rem Блок создания новой резервной копии
SET SrcData=D:\My Src
SET ArcName=%NewBkDir%\MySrc.rar
ECHO Архивация "%SrcData%" с помощью RAR >> "%LogFile%"
rar a -m5 -md4096 -ep1 -ri1 -dh -ilog"%LogFile%" "%ArcName%" "%SrcData%"

rem Соблюдение глубины архивации (должны остаться только последние %ARCDEPTH% каталогов)
ECHO Удаление старых бэкапов: >> "%LogFile%"
SET Index=0
rem DIR /AD /B /O-D "%DirName%" - получение упорядоченного по дате списка каталогов, начиная с самых новых
FOR /f "tokens=1" %%i IN ('DIR /AD /B /O-D "%DirName%"') DO (
	rem Первые %ArcDepth% архивов пропускаем, остальные удаляем
	SET /a Index+=1
	IF !Index! LEQ %ArcDepth% (
		echo "%DirName%\%%i" - оставлен >> "%LogFile%"
	) else (
		RMDIR /S/Q "%DirName%\%%i"
		echo "%DirName%\%%i" - удален >> "%LogFile%"
	)
)

ECHO ***** КОНЕЦ %DATE% %TIME%  ***** >> "%LogFile%"
ECHO. >> "%LogFile%"
ECHO. >> "%LogFile%"


Поскольку используется консольная версия архиватора RAR, необходимо, чтобы для скрипта был доступен RAR.exe. Для новых локализованных версий архиватора помимо файла RAR.exe также желательно наличие файла RarLng.dll, а для зарегистрированных пользователей — еще и файла rarreg.key. Для обеспечения доступности можно, например, просто положить все нужные файлы в рабочий каталог скрипта.

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

В переменных, содержащих пути к файлам/каталогам, можно использовать и абсолютные, и относительные пути, а также пробелы.

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

Резервные копии раскладываются в каталоги, имена которых содержат дату и время выполнения резервирования в следующем порядке: год, месяц, дата, часы, минуты, секунды, сотые доли секунды (справедливо для русских региональных настроек). Это необходимо для того, чтобы алфавитная сортировка списка резервных копий совпадала с сортировкой по дате/времени создания копий (то есть просто для удобства работы с копиями). В случае использования региональных настроек, в которых порядок следования элементов даты другой, для получения аналогичного эффекта необходимо изменить порядок токенов %%a-%%g в команде
SET NewBkDir=%DirName%\%%c.%%b.%%a_%%d.%%e.%%f.%%g


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

«Родная» кодировка для CMD-сценариев — OEM (866), а для Windows-версии архиватора RAR — ANSI (Windows-1251). В связи с этим лог-файл грешит некоторой неудобочитаемостью, если сценарий сохранить в родной для него OEM-кодировке. С одной строны, для себя я счел этот недостаток некритичным (в редакторе/просмотрщике Far Manager не трудно нажать F8 для смены кодировки), а с другой стороны ничто не мешает сохранить сценарий в кодировке ANSI (вывод в консоль командами ECHO в сценарии не используется — только в лог-файл, — поэтому пользователь никаких кракозяблов не увидит, зато лог будет нормально записываться в одной и той же кодировке). Буду благодарен, если предложите более корректный способ «подружить» эти кодировки.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.