СоХабр закрыт.

С 13.05.2019 изменения постов больше не отслеживаются, и новые посты не сохраняются.

H Рабоче-крестьянское резервное копирование под Windows в черновиках Из песочницы

Постановка задачи


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

Пусть задача будет звучать следующим образом:

  1. Необходимо организовать автоматическое резервное копирование определенных файлов компьютера на отдельный носитель.
  2. Компьютер работает под управлением Windows версий 7 / 2008 или более поздней.
  3. Объем данных большой, поэтому копирование должно поддерживаться как полное, так и дифференциальное.
  4. Д.б. возможность копировать любые файлы, в т.ч. системные, заблокированные на чтение и т. п.
  5. Сторонним платным софтом пользоваться категорически не хочется (ну, допустим, мы стеснены в средствах, а эти ваши торренты — не наш путь! Или религия не позволяет. Или миллион других причин.), а лучше вообще обойтись без любого стороннего софта, пользуясь лишь возможностями ОС .

Немного подумав, еще расширим список хотелок:

  1. Как продолжение предыдущего пункта, формат архива также должен быть открытым и распространенным, чтобы в случае чего его без проблем открыть откуда угодно с помощью чего-угодно
  2. Более того, он должен быть таким, чтобы из любого, даже дифференциального архива, можно было бы без труда вытащить любой файл, не распаковывая для этого весь архив.
  3. Глубина архивации должна настраиваться (что называется, backup rotate).
  4. Было бы неплохо также с архивом сохранять дескрипторы безопасности NTFS.
  5. И вообще, хочется максимальной расширяемости и настраиваемости, если завтра возникнет желание нагородить дополнительный функционал.

Что ж, требования сформулированы, дело за малым – спланировать и реализовать всё остальное.


Выбор средств


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

  • Алгоритмический язык и командлеты – Powershell (хотя тут при желании можно и VBScript)
  • Доступ к файлам через службу теневого копирования тома (VSS)
  • Формат архива – Zip
  • Механизм копирования только измененных файлов – архивный бит файловой системы
  • Автоматизация запусков – встроенный планировщик
  • ПО архивации – ?

Несморя на то, что через пользовательский интерфейс Windows создать «Сжатую ZIP-папку» проще простого, в результате поиска встроенного аналога командной строки меня постиг облом №1. Для реализации, собственно, функции архивирования для оригинальной Windows из коробки, к сожалению, так или иначе требовалась либо доустановка NET Framework, либо сторонних командлетов Powershell, либо файлов из Resource Kit, либо чего-то еще.

Опробовав ряд вышеперечисленных вариантов меня постиг облом №2: на больших объемах архивируемых данных (начиная от пары сотен гигабайт) одни попросту вылетали, другие съедали всю память и начинали грузить сервер, третьи еще каким-то образом начинали чудить.

Глубоко вздохнув, приходится делать шаг в сторону от одного из вышеозначенных принципов и взять на роль архиватора готовое решение. С точки зрения опенсорсности и бесплатности опять же практически безальтернативно выбор падает на:

  • ПО архивации – 7-Zip


План алгоритма


Итак, алгоритм предельно прост: пишем сценарий на Powershell, который должен:
  1. Исходя из переданных параметров, создать теневую копию интересуемого тома.
  2. Получить к ней доступ из операционной системы.
  3. В случае дифференциальной/инкрементной резервной копии составить список измененных файлов.
  4. Заархивировать нужные файлы.
  5. По возможности заархивировать NTFS ACL
  6. Удалить теневую копию.
  7. В случае создания полной/инкрементной резервной копии – сбросить с файлов архивный бит.
  8. В случае создания полной копии удалить старые бэкапы (старше заданной глубины архивации).


Скрипт


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

Итоговый скрипт backup-files.ps1
##################################################################################################
# Скрипт резервного копирования данных v0.9b
# 25-12-2014
# Accel
##################################################################################################
#
#Поддерживаются полные и дифференциальные копии (на основе архивного атрибута файлов)
#
#Системные требования: 
#	Windows 7+, 2008+
#	Установленный архиватор 7-Zip (тестировалось на версии 9.30b)
#
#За один запуск скрипта возможно резервное копирование лишь с одного диска
#
#NTFS-полномочия на данный момент не сохраняются (определяется возможностями архиватора)
#
#Скрипт должен запускаться от пользователя, имеющего доступ к архивируемым файлам (с правами SYSTEM, Backup Operator и т.п.)

$ErrorActionPreference="SilentlyContinue"
Stop-Transcript | out-null
$ErrorActionPreference = "Continue"

##################################################################################################
#Начало блока переменных
##################################################################################################

#Название задания архивирования
#Используется в именовании архива и ссылки на теневую копию
#Должно отвечать правилам именования файлов, наличие пробелов не рекомендуется, т.к. не тестировалось
#Пример: $ArchiveTaskName="DiskE"
$ArchiveTaskName="DiskE"

#Путь до диска-источника резервного копирования 
#Перечень целевых папок этого диска определяется отдельно
#Пример: $SrcDrivePath="D:\"
$SrcDrivePath="D:\"

#Путь до целевого диска 
#Пример: $BackupDrivePath="E:\"
$BackupDrivePath="E:\"

#Полный путь до файла со списком папок для архивирования на диске-источнике
#Пример: $SubfoldersToBackupFile = "E:\Backup\src_dirs.txt"
#	* Каждая строка данного файла должна содержать одну папку, которую мы хотим включить в архив
#	* Путь д.б. относительным, т.е. не содержать буквы диска.
#	* Иными словами, если одна из папок резервного копирования у нас D:\Files\FilesToBackup, то в файле должна быть строка Files\FilesToBackup
#	* Кодировка - ANSI
$SubfoldersToBackupFile = "E:\Backup\src_dirs.txt"

#Путь до временного файла-списка файлов для архивации:
#Пример: $BackupFilesList = "E:\Backup\backup-filelist.txt"
$BackupFilesList = "E:\Backup\backup-filelist.txt"

#Путь до целевой папки с архивами (В ней не должно быть никаких других файлов, иначе rotation их может удалить! Также лучше не использовать корень диска, а создать хоть одну подпапку.)
#Пример: $ArchiveDstPath = $BackupDrivePath+"Backup\Script backup"
$ArchiveDstPath = $BackupDrivePath+"Backup\Script backup"

#Полный путь до файла журнала задания
#Пример: $ScriptLogFile = "E:\Backup\BackupFiles.log"
$ScriptLogFile = "E:\Backup\BackupFiles.log"

#Путь до исполняемого файла архиватора 7-Zip
#Пример: $SevenZipExecutablePath = "C:\Program files\7-Zip\7z.exe"
$SevenZipExecutablePath = "C:\Program files\7-Zip\7z.exe"

#Количество дней хранения архива (отсчет ведется с последнего полного бэкапа)
#Пример: $BackupRotationIntervalDays=22
$BackupRotationIntervalDays=22

##################################################################################################
#Конец блока переменных
##################################################################################################


$BackupFilesListTmp = $BackupFilesList+".tmp"
$backuptype=$args[0]
$VSCPath = $BackupDrivePath+"VSC_"+$ArchiveTaskName+"_$(Get-Date -format "yyyyMMdd")"

Start-Transcript -path $ScriptLogFile

$LogVars=1

if ($LogVars=1) {
	echo "================================================================="
	echo "ArchiveTaskName: $ArchiveTaskName"
	echo "SrcDrivePath: $SrcDrivePath"
	echo "BackupDrivePath: $BackupDrivePath"
	echo "SubfoldersToBackupFile: $SubfoldersToBackupFile"
	echo "BackupFilesList: $BackupFilesList"
	echo "ArchiveDstPath: $ArchiveDstPath"
	echo "ScriptLogFile: $ScriptLogFile"
	echo "SevenZipExecutablePath: $SevenZipExecutablePath"
	echo "VSCPath: $VSCPath"
	echo "BackupRotationIntervalDays: $BackupRotationIntervalDays"
	echo "================================================================="
	}

echo "Backup started at: $(Get-Date)"

function BackupFull {
	echo "Backup type: full"
	
	#Создаем теневую копию
	$s1 = (gwmi -List Win32_ShadowCopy).Create($SrcDrivePath, "ClientAccessible")
	$s2 = gwmi Win32_ShadowCopy | ? { $_.ID -eq $s1.ShadowID }
	$d  = $s2.DeviceObject + "\"

	#Создаем на нее ярлык (удалим предыдущий, если остался после прерванной архивации)
	CMD /C rmdir "$VSCPath"
	cmd /c mklink /d $VSCPath "$d"

	#Составляем список папок для архивации
	"" | Set-Content $BackupFilesList
	Get-Content $SubfoldersToBackupFile | Foreach-Object {CMD /C "echo $VSCPath\$_\* >> $BackupFilesList" }
	
	#Создаем массив параметров для 7-Zip
	$Arg1="a"
	$Arg2=$ArchiveDstPath+"\"+$ArchiveTaskName+"_$(Get-Date -format "yyyy-MM-dd")_`(Full`).zip"
	$Arg3="-i@"+$BackupFilesList
	$Arg4="-w"+$ArchiveDstPath
	$Arg5="-mx=3"
	$Arg6="-mmt=on"
	$Arg7="-ssw"
	$Arg8="-scsUTF-8"
	$Arg9="-spf"

	#Зипуем
	& $SevenZipExecutablePath ($Arg1,$Arg2,$Arg3,$Arg4,$Arg5,$Arg6,$Arg7,$Arg8,$Arg9)
	
	Remove-Item $BackupFilesList

	#Если теневые копии имеют необъяснимую тенденцию копиться, лучше удалим их все
	#CMD /C "vssadmin delete shadows /All /Quiet"
	
	#Или можно удалить только конкретную созданную в рамках данного бекапа
	"vssadmin delete shadows /Shadow=""$($s2.ID.ToLower())"" /Quiet" | iex

	#Удаляем ярлык
	CMD /C rmdir $VSCPath

	#Снимаем архивный бит
	Get-Content $SubfoldersToBackupFile | Foreach-Object {CMD /C "attrib -A -H -S $SrcDrivePath$_\* /S /L" }
	
	#делаем rotation
	echo "Rotating old files..."
	CMD /C "forfiles /D -$BackupRotationIntervalDays /S /P ""$ArchiveDstPath"" /C ""CMD /C del @file"""
	}
	
function BackupDiff {
	echo "Backup type: differential"
	
	#Создаем теневую копию
	$s1 = (gwmi -List Win32_ShadowCopy).Create($SrcDrivePath, "ClientAccessible")
	$s2 = gwmi Win32_ShadowCopy | ? { $_.ID -eq $s1.ShadowID }
	$d  = $s2.DeviceObject + "\"

	#Создаем на нее ярлык (удалим предыдущий, если остался после прерванной архивации)
	CMD /C rmdir $VSCPath
	cmd /c mklink /d $VSCPath "$d"
	
	#Включаем UTF-8
	CMD /C "chcp 65001 > nul"
	
	#Составляем список файлов, измененных с момента предыдущей архивации
	"" | Set-Content $BackupFilesList
	Get-Content $SubfoldersToBackupFile | Foreach-Object {CMD /C "dir $VSCPath\$_ /B /S /A:A >> $BackupFilesList" }
	
	CMD /C "chcp 866 > nul"
	
	$SearchPattern="^"+$BackupDrivePath.Substring(0,1)+"\:\\"
	
	#Отрезаем букву диска, иначе 7-zip при архивации по списочному файлу глючит, находя несуществующие дубли
	#(Get-Content $BackupFilesList) -replace $SearchPattern,'' > $BackupFilesListTmp
	Get-Content $BackupFilesList | ForEach-Object { $_ -replace $SearchPattern,"" } | Set-Content ($BackupFilesListTmp)
	
	Remove-Item $BackupFilesList
	Rename-Item $BackupFilesListTmp $BackupFilesList
	
	#Поскольку имя диска в путях удалили, нужно перейти в нужную директорию
	cd $BackupDrivePath

	#Создаем массив параметров для 7-Zip
	$Arg1="a"
	$Arg2=$ArchiveDstPath+"\"+$ArchiveTaskName+"_$(Get-Date -format "yyyy-MM-dd")_`(Diff`).zip"
	$Arg3="-i@"+$BackupFilesList
	$Arg4="-w"+$ArchiveDstPath
	$Arg5="-mx=3"
	$Arg6="-mmt=on"
	$Arg7="-ssw"
	$Arg8="-scsUTF-8"
	$Arg9="-spf"

	#Зипуем
	& $SevenZipExecutablePath ($Arg1,$Arg2,$Arg3,$Arg4,$Arg5,$Arg6,$Arg7,$Arg8,$Arg9)
	
	Remove-Item $BackupFilesList

	#Если теневые копии имеют необъяснимую тенденцию копиться, лучше удалим их все
	#CMD /C "vssadmin delete shadows /All /Quiet"
	
	#Или можно удалить только конкретную созданную в рамках данного бекапа
	"vssadmin delete shadows /Shadow=""$($s2.ID.ToLower())"" /Quiet" | iex

	#Удаляем ярлык
	CMD /C rmdir $VSCPath
	}
	
if ($backuptype -eq "diff") {
	BackupDiff | Out-Host
	}
elseif ($backuptype -eq "full") {
	BackupFull | Out-Host
	}
else {
	echo $backuptype
	echo "None backup type parameter passed! Usage: scriptname.ps1 [ full | diff ]"
	}

echo "Backup finished at: $(Get-Date)"

Stop-Transcript



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

Файл папок-источников src_dirs.txt
bases
files
photos
users/profiles



Использование


Складываем всё в одну папку, и всё, можно запускать в Powershell. Единственный параметр — тип запуска [full | diff], определяет полный/дифференциальный способ копирования.

PS E:\Backup> .\backup-files.ps1 full


Убедившись, что всё работает (или поправив параметры, если нет) создаём задание в планировщике (отдельно для полного копирования и отдельно для дифференциального).

Экспортированный пример задания: scheduled-backup-task-full.xml
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <RegistrationInfo>
    <Date>2014-10-14T23:14:45.0256428</Date>
    <Author>PC\Accel</Author>
  </RegistrationInfo>
  <Triggers />
  <Principals>
    <Principal id="Author">
      <UserId>PC\User</UserId>
      <LogonType>S4U</LogonType>
      <RunLevel>HighestAvailable</RunLevel>
    </Principal>
  </Principals>
  <Settings>
    <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
    <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
    <AllowHardTerminate>true</AllowHardTerminate>
    <StartWhenAvailable>true</StartWhenAvailable>
    <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
    <IdleSettings>
      <StopOnIdleEnd>true</StopOnIdleEnd>
      <RestartOnIdle>false</RestartOnIdle>
    </IdleSettings>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>false</Hidden>
    <RunOnlyIfIdle>false</RunOnlyIfIdle>
    <DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession>
    <UseUnifiedSchedulingEngine>false</UseUnifiedSchedulingEngine>
    <WakeToRun>true</WakeToRun>
    <ExecutionTimeLimit>P3D</ExecutionTimeLimit>
    <Priority>7</Priority>
  </Settings>
  <Actions Context="Author">
    <Exec>
      <Command>C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe</Command>
      <Arguments>-Command "& {E:\Backup\backup-files.ps1 full}"</Arguments>
    </Exec>
  </Actions>
</Task>


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

Замечания


  • Для корректной работы (в первую очередь для создания теневой копии) powershell должен быть запущен от имени администратора (или «с наивысшими привилегиями» в терминологии планировщика заданий).
  • По идее способ также годится для горячего консистентного резервного копирования хоть баз MSSQL, хоть MS Exchange (при установке соотв. shadow copy providers, которые к подобному софту идут в комплекте), хотя конкретно в этих случаях удобнее пользоваться встроенными средствами.
  • Инкрементным резервным копированием я не пользуюсь (много хлопот найти удаленный файл среди кучи инкрементных архивов), но если возникнет потребность, то он получается буквально комбинированием нескольких срочек из полного и дифференциального блоков скрипта.
  • Здесь также не реализован механизм сохранения ACL (формат zip, да и 7zip не поддерживают хранение дескрипторов безопасности в архиве; RAR умеет, но это уже не свободное ПО, что сильно противоречит условиям задачи). В случае необходимости дескрипторы можно сохранять в файл встроенными утилитами типа icacls и добавлять полученный дамп в создаваемый архив.
  • Увы и ах, алгоритм не подходит для XP/2003. Сложность возникает на моменте создания ярлыка на теневую копию (в этих ОС нет утилиты mklink, а по-быстрому обойти эти грабли у меня не вышло).


P.S.


Перед необходимостью изобретать свой велосипед автор за несколько лет намучался перепробовал большое количество разнообразного бесплатного готового ПО со похожей функциональностью (Cobian Backup, COMODO Backup и др.). Вдоволь находившись по разнообразным встроенным в упомянутый софт граблям, было принято решение написать что-то своё. На данный момент описанное решение успешно работает на серверах (Windows Server 2008 R2) и рабочих станциях (Windows 7 и Windows 8.1).

Самая крупная создаваемая полная резервная копия на данный момент составляет 1 Тб в исходных файлах, в архиве – 350 Гб. При архивировании с зеркала SAS (7200) на такой же локальный Volume-диск (оба работают внутри vSphere, будучи подключенными как RDM Passthrough-диски) операция занимает около 6 часов, что в условиях задачи является вполне приемлемым результатом.
+12
17808

комментарии (41)

0
roman_pro ,  
Под XP/2003 для создания линков скорее всего поможет утилита junction
0
Aclz ,  
Да, я видел ее.
К сожалению, есть два момента:
  1. junction не входит в комплект XP/2003.
  2. При попытке скормить ей путь до теневой копии (вида "\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\"), ругается на то, что якобы данный том имеет файловую систему отличную от NTFS и ярлык не создает.
+1
lovecraft ,  
Bareos — Backup Archiving REcovery Open Sourced
Bareos is a 100% open source fork of the backup project from bacula.org.

Bareos 14.2 is the current stable. Here are some highlights:

Windows
  • Bareos server components run on Windows now
  • Better VSS support Volume Mount Points (VMP) supported
  • Windows Encrypted Filesystems (EFS) supported
  • Windows Dedup Support
  • System Registry key 'NotToBackup' supported
  • New installers for pre- and post Vista Windows versions
0
ikormachev ,  
Да, но зачем? Чем не устраивает встроенная в Windows система архивации?
0
ASD2003ru ,  
Для Bare-Metal бекапа еще ничего, но есть у нее ограничение. На сетевое хранилище только FullBackup.
0
ikormachev ,  
Подключаете сетевое хранилище по iSCSI и делаете инкрементальные бекапы.
0
Aclz ,   * (был изменён)
Зачастую он устраивает, но не всегда:
1. Конкретно iSCSI не всегда подходит для домашнего применения, да и в корпоративной инфраструктура не всегда имеется.
2. Также часто хочется дополнительного функционала (прикрутить оповещения на почту или еще что).
3. Если нужно бэкапить не весь том целиком, а лишь отдельные каталоги, то встроенная система этого делать не умеет.
4. Плюс, если просто всё бэкапить в один образ, так как это делает Windows Image Backup (и полные, и дифф. бэкапы), то потом возникают сложности с мониторингом наличия файлов бэкапа (когда создается по одному файлу на каждый день, гораздо проще контролировать, когда и какие копии не создались, какие создались, но почему-то оказались пустыми архивами (например, кончилось место на целевом диске) и т.п.).
0
ikormachev ,  
1. Конкретно iSCSI не всегда подходит для домашнего применения, да и в корпоративной инфраструктура не всегда имеется.

FreeNAS вам в помощь. А в домашней инфраструктуре бекапы вообще можно делать на подключенный локальный диски.

2. Также часто хочется дополнительного функционала (прикрутить оповещения на почту или еще что).

PowerShell и event-триггеры, встроенные в Windows. Настроить сообщения об ошибке резервного копирования можно без проблем.

3. Если нужно бэкапить не весь том целиком, а лишь отдельные каталоги, то встроенная система этого делать не умеет.

Это не умела делать только Windows 2008, начиная с R2 встроенная система позволяет делать бекап отдельных папок. В любом случае, при настройке резервного копирования делать бекап отдельных файлов — это резать сук на котором сидишь, потому что бекапы вроде и делались, но делались бекапы не всего.

4. Плюс, если просто всё бэкапить в один образ, так как это делает Windows Image Backup (и полные, и дифф. бэкапы), то потом возникают сложности с мониторингом наличия файлов бэкапа (когда создается по одному файлу на каждый день, гораздо проще контролировать, когда и какие копии не создались, какие создались, но почему-то оказались пустыми архивами (например, кончилось место на целевом диске) и т.п.).


Дифференциальные копии пишутся не в один файл, а в теневые копии и удаляются они по мере окончания места на диске — попробуйте отдельными файлами так забивать диск под завязку и головная боль вам обеспечена. В одном файле хранится последний бекап системы. С вашим же дифференциальным копированием вы замучаетесь восстанавливать папку по состоянию на «150 дней назад» — виндовый же бекап восстановит ее ровно в том состоянии, в котором она была на момент резервного копирования и сделает это в пару кликов. Вот скриншот с первого попавшегося сервера — все копии рабочие:

0
Aclz ,   * (был изменён)
FreeNAS вам в помощь. А в домашней инфраструктуре бекапы вообще можно делать на подключенный локальный диски.

Тут мы уходим немного в оффтоп, а точнее, в вопросы подходов построения ИТ-инфраструктуры :)
Нагородить iSCSI ТОЛЬКО ради функции дифференциального/инкрементного бэкапа в моем случае неоправданное роскошество. Наколенный файловый zip-бэкап поддерживать/разворачивать/и т.д. может и рядовой эникей после 10-минутного инструктажа. Разобраться с какой-либо проблемой NAS4Free, OMV и подобн. софтовых таргетов потребует привлечения сисадмина более высокого уровня. Итого при прочих равных (если нам не нужна time machine и состояние каждого файла на любой момент времени) стоимость владения инфраструктурой в описанном вами случае выше.

Это не умела делать только Windows 2008, начиная с R2 встроенная система позволяет делать бекап отдельных папок. В любом случае, при настройке резервного копирования делать бекап отдельных файлов — это резать сук на котором сидишь, потому что бекапы вроде и делались, но делались бекапы не всего.

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

Дифференциальные копии пишутся не в один файл, а в теневые копии и удаляются они по мере окончания места на диске — попробуйте отдельными файлами так забивать диск под завязку и головная боль вам обеспечена. В одном файле хранится последний бекап системы.

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

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

С вашим же дифференциальным копированием вы замучаетесь восстанавливать папку по состоянию на «150 дней назад» — виндовый же бекап восстановит ее ровно в том состоянии, в котором она была на момент резервного копирования и сделает это в пару кликов.

Не всё так страшно. Если надо восстановить папку по состоянию на 150 дней назад, восстанавливаем ее из последнего предшествующего интересуемой дате полного бэкапа, потом восстанавливаем поверх из одного-единственного дифференциального на дату now()-150 дней, всё. Поскольку запросы на восстановления — вещь не частая, то тут большой проблемы нет.
0
ikormachev ,  
Наколенный файловый zip-бэкап поддерживать/разворачивать/и т.д. может и рядовой эникей после 10-минутного инструктажа

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

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

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

Как в этом случае без лишней головной боли убедиться, и делать это на ежедневной основе в автоматическом режиме, что у меня на NN серверах, на которых делается такой бэкап, действительно наличествуют все резервные копии за все дни согласно политикам резервного копирования?

Достоверно сделать это можно только в ручном режиме. Мы у своих клиентов раз в месяц все бекапы проверяем вручную.

восстанавливаем ее из последнего предшествующего интересуемой дате полного бэкапа, потом восстанавливаем поверх из одного-единственного дифференциального на дату now()-150 дней, всё.

Для этого вам надо хранить полные бекапы 150-дневной давности, а это занимает дисковое пространство. Виндовый бекап позволяет хорошо экономить место в этом случае.
0
IvanovSV ,  
Исходная постановка задачи
Допустим, вы системный администратор в малой/средней компании


Ваше предложение:
Это должно быть на разных разделах диска, чтобы можно было играться настройками теневого копирования, квотирования и т.д…


Как вы себе представляете все это на обычной файлопомойке обычной мелкой конторы, с обычным эникеем?
0
ikormachev ,  
Разделы на диске эникей должен уметь создавать, а так виртуализация теперь доступна всем повсеместно.
0
IvanovSV ,  
А потом еще и динамические тома и т.д. Чтобы пользователь не шарился по разным дискам в поисках где у него что нужное находится.
Виртуализация… доступна всем повсеместно, как и симпатичный софт типа Vgate
+1
ildarz ,  
Как в этом случае без лишней головной боли убедиться, и делать это на ежедневной основе в автоматическом режиме, что у меня на NN серверах, на которых делается такой бэкап, действительно наличествуют все резервные копии за все дни согласно политикам резервного копирования?


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

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

И, кстати, по беглому взгляду на скрипт у вас две ошибки в логике полного бэкапа.

1. Для снятия архивного атрибута вы используете список файлов, полученный с основого тома после полного завершения операции бэкапа. Вопрос — каков будет результат, если после создания теневой копии данные на основном томе изменились?
2. Вы меняете атрибут, не убедившись, что задействованные в бэкапе команды не вернули ошибок.
0
Aclz ,   * (был изменён)
Вот как раз тут-то готовые решения подходят куда лучше, чем ваш скрипт. Вы же там ничего не отслеживаете — просто перенаправляете весь вывод в лог-файл.

Да, мониторинг всего и вся оставлен за скобками, т.к. он проверяет вообще все бэкапы, в т.ч. сделанные другими средствами.

1. Для снятия архивного атрибута вы используете список файлов, полученный с основого тома после полного завершения операции бэкапа. Вопрос — каков будет результат, если после создания теневой копии данные на основном томе изменились?
2. Вы меняете атрибут, не убедившись, что задействованные в бэкапе команды не вернули ошибок.

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

С ошибками интересная история. Это тоже некий компромисс текущих потребностей. Можно, конечно было и
$ErrorActionPreference = "Continue"
а после команды архивирования:
if ($LastExitCode -ne 0) {
		echo "Ошибка архивации!"
		return;
		}
но в этом случае, скажем, любые warning'и 7-Zip'а при архивировании (например, ему не понравилось какое-то имя файла, но в архив он его добавил) приводят к ненулевому коду возврата и недоведению скрипта до логического конца (не удаляется ярлык, теневая копия и т. п.).

И вообще, вот думал же написать Disclaimer в начале :)

Disclaimer
Этот скрипт не претендует на роль готового коммерческого решения для любых условий эксплуатации (заголовок как бы намекает), а является скорее основой для тех, кто хочет с минимумом допиливаний или без оных адаптировать его под свои конкретные потребности и создать предельно простой, но полностью подконтрольный и настраиваемый механизм архивации.
0
ildarz ,  
Очистка в конце (а не сразу после создания теневой копии) сделана из соображений избежания ситуации, когда мы сначала сняли архивный бит, а потом не смогли сделать полный бэкап и оперативно вручную не устранили проблему до момента создания следующего дифф. бэкапа.


У вас всё равно нет обработки ошибок, и бит в любом случае будет снят. Так лучше уж сделать это вовремя. :)) Если надо действительно избежать описанной ситуации, бит можно снимать в начале операции и ставить заново в конце, если бэкап закончен неуспешно. У 7zip несколько кодов возврата, не обязательно просто на ноль проверять.

В случае создания полной копии когда-нибудь в полночь воскресенья нюанс не критичен


В ситуации, когда это некритично (т.е. при копировании заведомо неизменяемых файлов), нет смысла вообще огород городить. Копировать сразу основной том штатным robocopy, и все дела.
+1
lovecraft ,  
И кстати, вы не пробовали подключать VSS-копии файлов от MS SQL Server к работающему серверу (например, пользователи запороли базу и нужно ее восстановить)? А то вас может ждать большой сюрприз…
0
Aclz ,   * (был изменён)
Честно — не пробовал.
Но если стоит служба SQL Server VSS Writer (идет в комплекте к MSSQL), то почему не должно работать?
Из описания службы: «Provides the interface to backup/restore Microsoft SQL server through the Windows VSS infrastructure.».
Я тем же образом делал бэкап баз Exchange (после чего успешно восстанавливал), у него тоже свой провайдер, так в процессе создания теневой копии прямо по сообщениям консоли видно, что он сначала доводит файлы Exchange в теневой копии до состояния консистентности, а потом уже создается сама копия:

Создание теневой копии томов, подлежащих архивации...
Выполнение проверки согласованности для приложения Exchange.
Выполняется архивация тома MAILSTORE(F:), (скопировано 0%).


Если бэкапить какую-нибудь СУБД, ничего не знающую о VSS, тогда, конечно, файл базы может в момент создания копии быть в каком угодно неконсистентном состоянии и дальнейшее примонтирование не удастся.
0
lovecraft ,  
У меня (с VSS, естественно), когда дошло до дела — MS SQL объявил, что файлы повреждены (как потом выяснилось, не понравилось состояние журнала), и без запуска со спецключами он их не примет. Было очень неожиданно )) Пришлось поднимать отдельный экземпляр MS SQL и работать с ним. В итоге все восстановил, но осадок остался. Пользуйтесь лучше штатными средствами MS SQL- с ними точно проблем не будет.
0
ASD2003ru ,  
Как такой скрипт работает с файлами имеющими длинные имена? Недавно писал скрипт, так там проблема с Get-Item (к примеру), обламывается на длинных именах, в гугле разные костыли есть но все или через сторонние библиотеки либо через robocopy :). Можно конечно через System.IO попробовать. К стати а чем Cobian не понравился, вроде все то же делает?
0
Aclz ,  
Cobian имеет ряд мелких, но досадных косяков, при этом разрабы не реагируют и давно нет новых версий.
Например, у меня почему-то не вышло создать архивы с глубиной более ~ около двух месяцев, он начинает удалять файлы старше какой-то даты не взирая на установленную глубину.

Также API теневых копий Cobian не работает с томами (не видит их), примонтированными некоторыми утилитами шифрования (например, BestCrypt) как Removable drives (т.е. когда не создается скрытая долларовая шара).

С длинными именами работает (по крайней мере сейчас проверил полный бэкап, отработал путь в 320 символов).
0
oia ,  
Также API теневых копий Cobian не работает с томами (не видит их), примонтированными некоторыми утилитами шифрования (например, BestCrypt)
так на таких томах vss нормально не работает
0
Aclz ,  
Могу лишь догадываться, что есть критерий «нормальности» в вашем понимании, но приведенный метод
Win32_ShadowCopy.Create()
с созданием теневой копии даже на таком томе успешно справляется.
0
oia ,  
BestCrypt да работает, обычно пользовался TrueCrypt: — нет возможности создавать VSS-копии, дам даже служба не работала Спутал их )))
0
Katzman ,  
У меня с Cobian была ситуация прямо противоположная — он не удалял старые бэкапы, диск забивался и бэкап не производился.
0
Makc666 ,  
Главный вопрос, как этот скрипт работает с файлами, которые заняты системой?
Можно делать backup очень долго, а потом выяснить, что много файлов в архив не попало, хотя бы по причине их сканирования антивирусом в момент резервного копирования.
0
Aclz ,  
Все файлы теневой копии таким образом доступны для чтения, хоть файлы реестра, хоть файл подкачки и т. п.

Вы можете в этом убедиться, запустив такой кусок скрипта в Powershell:

$s1 = (gwmi -List Win32_ShadowCopy).Create("C:\", "ClientAccessible")
$s2 = gwmi Win32_ShadowCopy | ? { $_.ID -eq $s1.ShadowID }
$d  = $s2.DeviceObject + "\"
cmd /c mklink /d d:\Disk-C-Shadow-Copy "$d"


На диске D Будет создан ярлык Disk-C-Shadow-Copy на содержимое диска C:, войдя в который можно открыть любой файл, на который у вас есть права на чтение.
0
Daedmen ,  
У crashplan.com/ сама утилита для инкрементального бекапа(на подобие time machine в MacOSX) бесплатная, и умеет бекапить на внешний диск или на любой компьютер в сети на котором она же стоит.
0
yosemity ,  
Что люди только не придумают лишь бы не использовать Bacula, BackupPC и прочие. Бакула, кстати умеет и VSS и ленточки
0
Aclz ,  
В любом случае спасибо за наводку! (хотя Bacula – тот еще Nero комбайн) В прошлом году на Тостере совсем ничего путнего по сабжу насоветовать мне не смогли.
0
yosemity ,   * (был изменён)
Сам использую BackupPC. Я сторонник следующей схемы: 1) сервер сам бекапит свои данные 2) складывает на сторонний сервер или себе же 3), а там его забирает сервер архивации. т.е. нагрузка на сам бекап-сервер минимизируется, версионность им же поддерживается, а еще и есть на край последний бекап на строннем сервере.

Забыл, уточню. Теневые копии сам сервер по-любому умеет.
0
ya_petrov ,  
Bacula — прекрасная вещь. Статей, даже на Хабре великое множество, даже в картинках есть. Не без недостатков, конечно, но работает четко, как часы. Необходимо потратить время, разобраться, но не более того, что вы потратили на написание скрипта.
+2
dkopitsa ,  
Попробуйте Duplicati.
Бесплатный, open source, эффективное инкрементальные копирование на Amazon S3, Windows Live SkyDrive, Google Drive (Google Docs), Rackspace Cloud Files or WebDAV, SSH, FTP и т.д.

Для безопасности резервные копии могут шифроваться с помощью AES-256 / GnuPGP.
Сейчас идет активная разработка версии 2.0 (github)
0
navion ,  
Для Windows есть отличный Veeam Endpoint Backup, не пробовали его?
0
Aclz ,  
Нет, не пробовал. Но в любом случае вам и коллегам выше спасибо за совет! Будет повод — обязательно опробую вышеупомянутые решения.
0
yosemity ,   * (был изменён)
Veeam очень хорош, но без костылей нет регулярного бекапа. К тому же, для бесплатного ESXi не выстрелит. Ради бесплатного бекапа Veeam купили vSphere Essentials
0
navion ,  
Путаете B&R, Endpoint — это новый продукт для резервного копирования физических компьютеров, абсолютно бесплатный (по крайней мере пока).
0
Zagrebelion ,   * (был изменён)
Мне про Veeam Endpoint Backup интересна одна вещь: чем он занимается?
Я его в течении пары недель гонял по %userprofile% (70 гигов, в том числе архив фоточек, пачка виртуалок, документы. Ежедневного изменения — несколько мегабайт). Так он инкрементальный бакап делал минимум 4 часа (встроенная в Windows 7 архивация управляется минут за 40).

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

VEB делает один полный бакап, а каждый раз инкрементный. Через несколько дней (настраивается) он мержит полный бакап и первый инкрементальный, тем самым дата полного бакапа сдвигается. Завтра он смержит новый полный бакап и первый инкрементальный и т.п.
0
wnt_brian ,  
Спасибо за статью, мне очень импонируют эти ламповые самописные скрипты. Почему-то в сознании к ним больше доверия, чем к новомодным veeam и прочим, цель которых явно подсадить пользователя на продукт и раскрутить его. Это же бизнес.
А постановка задачи очень близка. Обязательно буду использовать ваш накопленный опыт.
0
RouR ,  
Я использую Cobian Backup, очень доволен. Архив делается по таймеру, в зашифрованный архив, хранится N последних копий + можно вручную отметить копию как неудаляемую. VSS есть. Дифы есть. А вообще вы плохо гуглите en.wikipedia.org/wiki/List_of_backup_software
0
KEKSOV ,  
Мне очень нравится Macrium Reflect, есть и бесплатная версия, неоднократно выручала при восстановлении системы после дисковых крэшей. До этого перепробовал массу других решений, у всех какие-то косяки. Характерный момент — в своей жизни купил всего три программы «для себя»: The Bat! (перестал пользоваться с появлением GMail), Total Commander и Macrium Reflect :) Не жалко $60 за надежную вещь, работающую как швейцарские часы. Последнее время, стал использовать следующую схему резервирования данных для офисных «серверов» — два SSD 120Г в зеркале для системы, два 1T в зеркале для данных и один 1T диск для складывания архивов, которые делает Macrium. Опционально подключаю GDrive ($10 в месяц за 1T) для переноса бекапов в облако. Для справки, восстановление данных с физически убитого диска стоит от 9000 руб. (http://rlab.ru/)

Поддерживаю автора статьи за желание использовать встроенные средства ОС. Сам написал машину времени на bat файлах (хотя, можно было написать на чем угодно другом, но мне захотелось экзотики) для живого бекапирования MySQL баз данных, которые используются в нашей конторе при разработке. Кончилось тем, что bat (чистый cmd.exe) файлы меня настолько выбесили своей непригодностью написать что-то удобоваримое, что пришлось сваять свою квазимоду надстройку-компилятор (правда, уже на JS) и теперь я наслаждаюсь конструкциями типа:
:procedure.FullDump
%begin%

%end.proc%

наверно, надо будет написать статью об этом в рубрику «Программные курьёзы»… хотя, этот «курьёз» уже неоднократно выручал коллег от случайных потерь таблиц и прочих встроенных процедур, которые при разработке ПО случаются регулярно…