Как известно, люди делятся на тех, кто ещё не делает бекапы, и тех кто уже делает. Я предпочитаю использовать для дома следующую схему: не часто, но периодически делаю полный бекап системы на случай глобального факапа, а также, гораздо чаще сохраняю важные данные (и храню большее количество версий). Под важными данными я понимаю рабочие файлы, настройки программ, базы данных. И данные бекапы также используются для восстановления случайно удалённых или изменённых файлов без полного отката системы.
Сегодня же, я хочу рассказать, как сделать бекап самого ценного для винды, а именно реестра. Дело в том, что в настоящий момент, практически всё необходимое для жизни винды хранится именно там. Вплоть до того, что если у вас есть сохранённая копия реестра, то вы можете поставить новую систему, и подменить ей реестр. И она заработает как старая, со всеми предыдущими настройками! Конечно, есть некоторые оговорки: повалятся некоторые сервисы и программы, будут проблемы с драйверами. Но эти проблемы можно уже решить в рабочем порядке. Главное — на вас не будет смотреть голая система.
Кому-то такое покажется странным, ведь некоторые люди переставляют систему постоянно, или периодически по настроению, и любят всё настраивать идеально (а через несколько месяцев — повторить). Я же подобное не люблю, и у меня в системе попадаются ошмётки десятилетней давности, просто потому что я привык к своему рабочему инструменту, и не хочу что-то кардинально менять без веской причины и привыкать заново.
В общем, если вам относительно близко моё мнение, я расскажу, как сохранить реестр, чтобы в случае непредвиденных проблем можно было его восстановить и продолжить работать в существующей системе не переставляя заново.
В данном куске скрипта мы через WMI создаём теневую копию, получаем её идентификатор, и монтируем её в качестве симлинка в текущей папке (с названием как идентификатор теневой копии).
Используя данный скрипт уже можно вручную скопировать файлы. Ну или автоматически, примерно так:
В данном скрипте мы собираем список файлов для архивирования во временный файл, и передаём его архиватору 7z, чтобы он уже самостоятельно проделал всю необходимую работу.
Дальше мы удаляем лишнюю копию:
И лишние файлы:
Скрипт целиком можно взять тут: backup-registry.7z (вместе с 7zip). В скрипте надо будет поправить необходимые пути и настроить его на периодическое выполнение, например, раз в день (что мелочиться-то?).
Также, можете его изменить чтобы архивировать не только данные файлы, но и другие, или придумать ещё более оригинальный способ использования. Можете оставлять комментарии с идеями.
Сегодня же, я хочу рассказать, как сделать бекап самого ценного для винды, а именно реестра. Дело в том, что в настоящий момент, практически всё необходимое для жизни винды хранится именно там. Вплоть до того, что если у вас есть сохранённая копия реестра, то вы можете поставить новую систему, и подменить ей реестр. И она заработает как старая, со всеми предыдущими настройками! Конечно, есть некоторые оговорки: повалятся некоторые сервисы и программы, будут проблемы с драйверами. Но эти проблемы можно уже решить в рабочем порядке. Главное — на вас не будет смотреть голая система.
Кому-то такое покажется странным, ведь некоторые люди переставляют систему постоянно, или периодически по настроению, и любят всё настраивать идеально (а через несколько месяцев — повторить). Я же подобное не люблю, и у меня в системе попадаются ошмётки десятилетней давности, просто потому что я привык к своему рабочему инструменту, и не хочу что-то кардинально менять без веской причины и привыкать заново.
В общем, если вам относительно близко моё мнение, я расскажу, как сохранить реестр, чтобы в случае непредвиденных проблем можно было его восстановить и продолжить работать в существующей системе не переставляя заново.
Где хранится реестр?
Он хранится в нескольких файлах. Во-первых, в папке C:\Windows\System32\config\ Там находятся файлы вида SYSTEM, SOFTWARE, SAM, COMPONENTS, DRIVERS. Это соответствующие ветки реестра. Например, SYSTEM — информация о сервисах и драйверах, SOFTWARE — установленные драйвера, SAM — данные о пользователях с внутренними идентификаторами и паролями (именно данная ветка обычно хорошо так меняется при установке, из-за чего система становится "особенно другой").
Также в этой папке находится системный профиль (профиль компьютера, который с точки зрения системы почти настоящий пользователь), и всякая другая мелочёвка.
При перезагрузке системы копия реестра сохраняется в папке RegBack. Я не очень представляю, когда данные из RegBack могут использоваться автоматически, но в случае проблем можно попытаться подменить файлы реестра из данной папки, чтобы восстановить работоспособность.
Также, в папке с профилем каждого пользователя (C:\Users\username\) находится файл ntuser.dat, являющийся реестром для данного пользователя.
Собственно, эти файлы мы и будем архивировать.
Как сделать архивную копию?
Какзалось бы, просто взять и скопировать. Но не всё так просто. Дело в том, что данные файлы заблокированы системой (справедливости ради, из RegBack можно достать файлы достаточно просто, но они будут не очень свежими в случае отсутствия перезагрузок, да и реестр пользователя не архивируется самостоятельно).
Т.е. с большинством файлов ничего не сделать на рабочей системе. В качестве аварийного решения, можно загрузиться в recovery режиме или с установочного диска/флешки, и вручную заархивировать данные файлы. Но данный вариант обычно используется, когда всё плохо, и данная копия делается при попытке восстановления, на случай, если после восстановления станет ещё хуже и надо будет откатиться.
Мы же не будем искать аварийных путей, и займёмся использованием встроенных средств Windows, а именно Volume Shadow Copy, теневой копией.
При создании теневой копии диска, создаётся снимок всей файловой системы на заданный момент времени, с неизменяемыми файлами. Который можно использовать для чтения заблокированных файлов или использовать в качестве версии файлов на определённый момент времени (так работает System Restore в Windows, она делает примерно тоже самое, в определённых случаях).
Итак, что надо сделать:
- Сделать теневую копию диска
- Подмонтировать её симлинком для удобства работы
- Скопировать нужные файлы
- Удалить копию
Всё это можно сделать из консоли, используя стандартные утилиты, я для удобства написал всё это на Powershell.
Итак по пунктам (полный скрипт в конце поста):
Делаем теневую копию и монтируем её:
Function CreateShadow($disk)
{
# e.g. c: -> c:\
$disk = $disk[0] + ':\';
$shadowObj = (gwmi -List Win32_ShadowCopy).Create($disk, "ClientAccessible")
$currentShadow = gwmi Win32_ShadowCopy | ? { $_.ID -eq $shadowObj.ShadowID }
$shadowID = $currentShadow.ID
$name = $currentShadow.DeviceObject + "\"
$dummy = cmd /c "mklink /d .\$shadowID $name"
Write-Host $dummy
return $shadowID
}
{
# e.g. c: -> c:\
$disk = $disk[0] + ':\';
$shadowObj = (gwmi -List Win32_ShadowCopy).Create($disk, "ClientAccessible")
$currentShadow = gwmi Win32_ShadowCopy | ? { $_.ID -eq $shadowObj.ShadowID }
$shadowID = $currentShadow.ID
$name = $currentShadow.DeviceObject + "\"
$dummy = cmd /c "mklink /d .\$shadowID $name"
Write-Host $dummy
return $shadowID
}
В данном куске скрипта мы через WMI создаём теневую копию, получаем её идентификатор, и монтируем её в качестве симлинка в текущей папке (с названием как идентификатор теневой копии).
Используя данный скрипт уже можно вручную скопировать файлы. Ну или автоматически, примерно так:
Function PerformBackup($shadowPath, $bakRoot)
{
if ($shadowPath -like '%\')
{
$shadowPath = $shadowPath.SubString(0, $shadowPath.Length - 1)
}
if ($bakPath -like '%\')
{
$bakPath = $bakPath.SubString(0, $bakPath.Length - 1)
}
$tmpFile = "$PWD\tmpFileList.txt"
# if script was incorrectly finished
if (Test-Path $tmpFile)
{
Remove-Item $tmpFile
}
Get-ChildItem -Recurse "$($shadowPath)\Windows\System32\Config" -Force -ErrorAction Continue | % { $_.FullName.Remove(0, $shadowPath.Length + 1) | Out-File -FilePath $tmpFile -Encoding ascii -Append }
Get-ChildItem "$($shadowPath)\Users\" -Directory | % { Get-ChildItem -File -Force "$($_.FullName)\ntuser.*" -ErrorAction SilentlyContinue | % { $_.FullName.Remove(0, $shadowPath.Length + 1) | Out-File -FilePath $tmpFile -Encoding ascii -Append } }
$archName = Get-Date -Format 'yyyyMMdd'
# if file exists, using _1, _2, ...
$archPath = $bakRoot + '\' + $archName;
$iterator = 1;
while (Test-Path "$archPath.7z")
{
$archPath = $bakRoot + '\' + $archName + '_' + $iterator;
$iterator++;
}
$curPWD = $PWD
cd $shadowPath
cmd /c "$($curPWD)\7z.exe a -m0=LZMA2 $archPath.7z @$tmpFile"
cd $curPWD
Remove-Item $tmpFile
}
{
if ($shadowPath -like '%\')
{
$shadowPath = $shadowPath.SubString(0, $shadowPath.Length - 1)
}
if ($bakPath -like '%\')
{
$bakPath = $bakPath.SubString(0, $bakPath.Length - 1)
}
$tmpFile = "$PWD\tmpFileList.txt"
# if script was incorrectly finished
if (Test-Path $tmpFile)
{
Remove-Item $tmpFile
}
Get-ChildItem -Recurse "$($shadowPath)\Windows\System32\Config" -Force -ErrorAction Continue | % { $_.FullName.Remove(0, $shadowPath.Length + 1) | Out-File -FilePath $tmpFile -Encoding ascii -Append }
Get-ChildItem "$($shadowPath)\Users\" -Directory | % { Get-ChildItem -File -Force "$($_.FullName)\ntuser.*" -ErrorAction SilentlyContinue | % { $_.FullName.Remove(0, $shadowPath.Length + 1) | Out-File -FilePath $tmpFile -Encoding ascii -Append } }
$archName = Get-Date -Format 'yyyyMMdd'
# if file exists, using _1, _2, ...
$archPath = $bakRoot + '\' + $archName;
$iterator = 1;
while (Test-Path "$archPath.7z")
{
$archPath = $bakRoot + '\' + $archName + '_' + $iterator;
$iterator++;
}
$curPWD = $PWD
cd $shadowPath
cmd /c "$($curPWD)\7z.exe a -m0=LZMA2 $archPath.7z @$tmpFile"
cd $curPWD
Remove-Item $tmpFile
}
В данном скрипте мы собираем список файлов для архивирования во временный файл, и передаём его архиватору 7z, чтобы он уже самостоятельно проделал всю необходимую работу.
Дальше мы удаляем лишнюю копию:
Function DropShadow($shadowID)
{
$dummy = cmd /c "rmdir .\$shadowID"
Write-Host $dummy
$currentShadow = gwmi Win32_ShadowCopy | ? { $_.ID -eq $shadowID }
$currentShadow.Delete()
}
{
$dummy = cmd /c "rmdir .\$shadowID"
Write-Host $dummy
$currentShadow = gwmi Win32_ShadowCopy | ? { $_.ID -eq $shadowID }
$currentShadow.Delete()
}
И лишние файлы:
Function RemoveOldBackups($bakPath)
{
dir $bakPath | ? { $_.CreationTime -le $(Get-Date).AddDays(-30) } | Remove-Item
}
{
dir $bakPath | ? { $_.CreationTime -le $(Get-Date).AddDays(-30) } | Remove-Item
}
Скрипт целиком можно взять тут: backup-registry.7z (вместе с 7zip). В скрипте надо будет поправить необходимые пути и настроить его на периодическое выполнение, например, раз в день (что мелочиться-то?).
Также, можете его изменить чтобы архивировать не только данные файлы, но и другие, или придумать ещё более оригинальный способ использования. Можете оставлять комментарии с идеями.