Резервные копии в Windows по сети

Используемые средства

К сожалению, Windows по сравнению с *nix-системами имеет очень слабый функционал для подготовки и копирования бэкапов. В последнее время имеется тенденция к улучшению (PowerShell), однако, полезных утилит все равно недостаточно. Обычные Windows-утилиты copy/xcopy очень плохо работают на большом количестве файлов. В интернете можно найти «продвинутую» версию xcopy под названием robocopy, именно её мы и будем использовать.

Полные бэкапы

Будем размещать резервные копии на сервере srv-bak. Копировать будем в сетевую шару \\srv-bak\bak\srv01, где srv01 — директория с именем сервера на бэкапном. Таким образом в одной директории будут храниться бэкапы с разных серверов.
На сервере с резервными копиями для каждой из них будем создавать директорию с текущей датой в качестве имени. Для удобства поместим исходные пути, которые нужно забэкапить, в файлик D:\backup\dirs.txt. Переносим всё это дело «на клавиатуру» и получаем такой скрипт:

set backupdir=\\srv-bak\bak\srv01
IF NOT EXIST %backupdir% (
	mkdir %backupdir%
)

set d=%date:~0,2%
set m=%date:~3,2%
set y=%date:~6,4%
set ndate=%y%%m%%d%

set dirsfile=D:\backup\dirs.txt

set dstpath=%backupdir%\%ndate%
IF NOT EXIST %dstpath% (
	mkdir %dstpath%
)

for /f "eol=; tokens=1 delims=" %%i in (%dirsfile%) do (
	mkdir "%dstpath%%%~pi%%~ni"
	robocopy "%%~di%%~pi%%~ni" "%dstpath%%%~pi%%~ni" /E /ZB /NP
)

Чтобы всё работало автоматически, добавляем скрипт в планировщик. Таким (простым!) способом можно бэкапить достаточно большие объемы. Единственный, но существенный, наблюдаемый баг — если какой-то из копируемых файлов занят, скрипт отработает некорректно.

Инкрементные/дифференциальные бэкапы

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

set backupdir=\\srv-bak\bak\srv01
IF NOT EXIST %backupdir% (
	mkdir %backupdir%
)

set d=%date:~0,2%
set m=%date:~3,2%
set y=%date:~6,4%
set ndate=%y%%m%%d%

if "%d%"=="01" (
	set dstpath=%backupdir%\%ndate%
) ELSE (
	set dstpath=%backupdir%\d%ndate%
)

IF NOT EXIST %dstpath% (
	mkdir %dstpath%
)

set /A prev=1%d%-100-1
if %prev% LSS 10 (
	set prev=0%prev%
)

set dirsfile=D:\backup\dirs.txt

if "%d%"=="01" (
	for /f "eol=; tokens=1 delims=" %%i in (%dirsfile%) do (
		:: xcopy "%%~di%%~pi%%~ni" "%dstpath%%%~pi%%~ni\" /C /E /H /Y
		mkdir "%dstpath%%%~pi%%~ni"
		robocopy "%%~di%%~pi%%~ni" "%dstpath%%%~pi%%~ni" /E /ZB /NP
	)
) ELSE (
	for /f "eol=; tokens=1 delims=" %%i in (%dirsfile%) do (
		:: xcopy "%%~di%%~pi%%~ni" "%dstpath%%%~pi%%~ni\" /D:%m%-%prev%-%y% /C /S /H /Y
		mkdir "%dstpath%%%~pi%%~ni"
		robocopy "%%~di%%~pi%%~ni" "%dstpath%%%~pi%%~ni" /MAXAGE:2 /S /ZB /NP
		rmdir "%dstpath%%%~pi%%~ni"
	)
)

IF EXIST %dstpath% (
	rmdir %dstpath%
)

Заключительные замечания

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

find -mindepth 2 -maxdepth 2 -type d -ctime +7 -execdir /usr/local/bin/tar_and_remove.sh "{}" \;

или

find -mindepth 2 -maxdepth 2 -type d -ctime +7 -execdir rar a -t -m5 -r -rr1 -df -inul "{}.rar" "{}" \; &> /dev/null

Кроме этого, с никсового сервера эти бэкапы очень удобно копировать с помощью ssh/scp/rsync.

Добавить комментарий

Ваш адрес email не будет опубликован.