MCP

суббота, 16 ноября 2013 г.

Windows, делаем бекап самого дорогого

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

Сегодня же, я хочу рассказать, как сделать бекап самого ценного для винды, а именно реестра. Дело в том, что в настоящий момент, практически всё необходимое для жизни винды хранится именно там. Вплоть до того, что если у вас есть сохранённая копия реестра, то вы можете поставить новую систему, и подменить ей реестр. И она заработает как старая, со всеми предыдущими настройками! Конечно, есть некоторые оговорки: повалятся некоторые сервисы и программы, будут проблемы с драйверами. Но эти проблемы можно уже решить в рабочем порядке. Главное — на вас не будет смотреть голая система.

Кому-то такое покажется странным, ведь некоторые люди переставляют систему постоянно, или периодически по настроению, и любят всё настраивать идеально (а через несколько месяцев — повторить). Я же подобное не люблю, и у меня в системе попадаются ошмётки десятилетней давности, просто потому что я привык к своему рабочему инструменту, и не хочу что-то кардинально менять без веской причины и привыкать заново.

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

Где хранится реестр?

Он хранится в нескольких файлах. Во-первых, в папке 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, она делает примерно тоже самое, в определённых случаях).

Итак, что надо сделать:
  1. Сделать теневую копию диска
  2. Подмонтировать её симлинком для удобства работы
  3. Скопировать нужные файлы
  4. Удалить копию
Всё это можно сделать из консоли, используя стандартные утилиты, я для удобства написал всё это на 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
}

В данном куске скрипта мы через 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
}

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

Дальше мы удаляем лишнюю копию:
Function DropShadow($shadowID)
{
    $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
}

Скрипт целиком можно взять тут: backup-registry.7z (вместе с 7zip). В скрипте надо будет поправить необходимые пути и настроить его на периодическое выполнение, например, раз в день (что мелочиться-то?).

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

Комментариев нет:

Отправить комментарий