还原 Microsoft Azure 包:网站

 

适用于:Windows Azure Pack

强烈建议还原到其名称和管理帐户与备份期间相同的服务器。 为使还原成功,文件服务器和 SQL Server 的配置、用户和权限必须与备份期间完全相同。 在还原网站服务时,请使用以下顺序:

1. 还原SQL Server数据库

2. 还原文件服务器

3. 还原网站控制器

4. 在所有角色上运行修复

可使用脚本执行还原操作。 下面详细介绍各个步骤。

1. 还原SQL Server数据库

还原 SQL Server 托管、资源计量和 master 数据库。 SQL Server 的名称必须与其备份时相同。

示例 SQL 还原脚本

提供以下示例脚本仅供说明用途,不支持该脚本。 必须以管理权限运行由您创建的脚本。

注意

Microsoft 不支持此脚本。

param ([string] $backupUser = "Administrator", $backupPassword, $sqlServer, $sqlUser = "sa", $sqlPassword, $backupLocation = "\\backupMachine\c$\backup" )
net use $backupLocation /user:$backupUser $backupPassword
xcopy /Y /q \\$backupMachine\c$\$backupLocation\Hosting.bak C:\HostingOfflineFeed\
xcopy /Y /q \\$backupMachine\c$\$backupLocation\ResourceMetering.bak C:\HostingOfflineFeed\
xcopy /Y /q $backupLocation\master.bak C:\HostingOfflineFeed\
net start "SQL Server (MSSQLSERVER)" /f
sqlcmd -S $sqlServer -U $sqlUser -P $sqlPassword -Q "RESTORE DATABASE [master] FROM DISK='C:\HostingOfflineFeed\master.bak' WITH REPLACE"
net stop "SQL Server (MSSQLSERVER)"
net start "SQL Server (MSSQLSERVER)"
sqlcmd -S $sqlServer -U $sqlUser -P $sqlPassword -Q "RESTORE DATABASE [Hosting] FROM DISK='C:\HostingOfflineFeed\Hosting.bak' WITH REPLACE"
sqlcmd -S $sqlServer -U $sqlUser -P $sqlPassword -Q "RESTORE DATABASE [ResourceMetering] FROM DISK='C:\HostingOfflineFeed\ResourceMetering.bak' WITH REPLACE"
del C:\HostingOfflineFeed\Hosting.bak
del C:\HostingOfflineFeed\ResourceMetering.bak
del C:\HostingOfflineFeed\master.bak

2. 还原文件服务器

文件服务器的名称必须与其备份时相同。 应按以下顺序还原文件服务器组件:

  1. 还原证书共享

  2. 还原网站共享

  3. 如有必要,重新应用 ACL

  4. 在网站共享上重新应用 FSRM 配额

下面提供两个示例脚本:一个用于上方的 1 到 3 步,另一个用于在网站共享上重新应用 FSRM 配额。

示例文件服务器还原脚本

以下示例步骤包括上方的 1-3 步(其中不还原 FSRM 配额)。 提供该脚本仅供说明用途,不支持该脚本。 必须以管理权限运行由您创建的脚本。

注意

Microsoft 不支持此脚本。

param ([string] $backupUser = "Administrator", $backupPassword, $certificateFolder = "C:\Certificates", $websiteFolder = "C:\websites", $backupLocation = "\\backupMachine\c$\backup" )
net use $backupLocation /user:$backupUser $backupPassword
mkdir $certificateFolder
mkdir $websiteFolder
xcopy /Y /q /E $backupLocation\ $certificateFolder
xcopy /Y /q /E $backupLocation\ $websiteFolder

还原 FSRM 配额的示例脚本

以下示例脚本还原 FSRM 配额。 提供该脚本仅供说明用途,不支持该脚本。 必须以管理权限运行由您创建的脚本。

注意

Microsoft 不支持此脚本。

param ([string] $backupUser = "Administrator", $backupPassword, $backupLocation = "\\backupMachine\c$\backup" )
net use $backupLocation /user:$backupUser $backupPassword
xcopy /Y /q $backupLocation\templates.xml C:\templates.xml
dirquota template import /File:C:\templates.xml
net stop srmReports
net stop srmSvc
net stop quota
net stop Datascrn
robocopy $backupLocation\SRM "C:\System Volume Information\SRM" /E /ZB /R:3 /W:5
net start Datascrn
net start quota
net start srmSvc
net start srmReports

3. 还原网站控制器

要还原网站控制器,可使用本节中给出的 Restore.ps1 PowerShell 脚本。

将 Restore.ps1 脚本复制到网站控制器上,然后用管理员权限运行以下命令:

net use /Y $backupLocation /user:$backupMachineAdmin $backupMachinePassword
.\Restore.ps1 $backupLocation $encryptionKey

注意

仅在备份期间使用 $encryptionKey 标志时才需要它。

Restore.ps1 脚本如下。

##  Re-install and restore the controller from a backup

param ($backupPath,$password)

function ShowHelp
{
    Write-Host '===================== RESTORE.PS1 HELP ====================='
    Write-Host 'This is a script that restores based on a backup from the Hosting VSS writer'
    Write-Host 'Invoke it using .\Restore.ps1'
    Write-Host 'It can also be invoked as follows:'
    Write-Host '.\Restore.ps1 <backup path (e.g. \\backupmachine\C$\backuplocation)> <password for keys file>' 
    Write-Host ("Note: before running this script you may need to run:`r`n" + ' "net use /Y <backup path> /user:<username> <password>"')
    Write-Host '============================================================'
}

function CreateFeedWebAppIfNeeded ([string] $localFeedLocation)
{
    import-module WebAdministration
    $app = Get-WebApplication -Name HostingOfflineFeed 
    if ($app -eq $null) 
    {
        New-WebApplication -Name HostingOfflineFeed -Site 'Default Web Site' -PhysicalPath $localFeedLocation -ApplicationPool DefaultAppPool -Force
    }
    # Add mime types needed for downloading .msp files for offline installations
    $msp = Get-WebConfiguration //staticContent/* | where {$_.fileExtension -eq '.msp'}
    if ($msp -eq $null) 
    {
        Add-WebConfiguration //staticContent -Value @{fileExtension=".msp";mimeType="application/octet-stream"}
    }

    # Add mime types needed for downloading .msu files for offline installations
    $msu = Get-WebConfiguration //staticContent/* | where {$_.fileExtension -eq '.msu'}
    if ($msu -eq $null) 
    {
        Add-WebConfiguration //staticContent -Value @{fileExtension=".msu";mimeType="application/octet-stream"}
    }
}

function InstallController ([string]$offlineFeedUrl, [string]$customFeed) 
{
    $WebPiCmd = ([System.Environment]::ExpandEnvironmentVariables("%ProgramW6432%\Microsoft\Web Platform Installer\WebpiCmd.exe"))    
    if (!(Test-Path $WebPiCmd))
    {
        $WebPiCmd = Join-Path -Path $localFeedLocation -ChildPath "bin\WebpiCmd.exe"
    }
    Invoke-Command -ScriptBlock { & $WebPiCmd /Install /Products:HostingController /AcceptEula /XML:$offlineFeedUrl /SuppressReboot /Log:HostingController.log }

    if ($lastexitcode -ne $null -And $lastexitcode -ne 0) 
    {
        Write-Host "ERROR: There was a problem installing using WebPI!"
        exit $lastexitcode
    }
}

function DecodeBase64($string)
{
    return [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($string))
}

function DecryptString($EncryptedFile, $Passphrase, $salt, $init) 
{ 
    $encryptedStrings = (Get-Content $EncryptedFile)
    $ret = @()
    foreach ($Encrypted in $encryptedStrings)
    {
        # If the value in the Encrypted is a string, convert it to Base64 
        if($Encrypted -is [string])
        { 
            $Encrypted = [Convert]::FromBase64String($Encrypted) 
        } 
        # Create a COM Object for RijndaelManaged Cryptography 
        $r = new-Object System.Security.Cryptography.RijndaelManaged 
        # Convert the Passphrase to UTF8 Bytes 
        $pass = [Text.Encoding]::UTF8.GetBytes($Passphrase) 
        # Convert the Salt to UTF Bytes 
        $salt = [Text.Encoding]::UTF8.GetBytes($salt) 
        # Create the Encryption Key using the passphrase, salt and SHA1 algorithm at 256 bits 
        $r.Key = (new-Object Security.Cryptography.PasswordDeriveBytes $pass, $salt, "SHA1", 5).GetBytes(32) #256/8 
        # Create the Intersecting Vector Cryptology Hash with the init 
        $r.IV = (new-Object Security.Cryptography.SHA1Managed).ComputeHash( [Text.Encoding]::UTF8.GetBytes($init) )[0..15]
        # Create a new Decryptor 
        $d = $r.CreateDecryptor() 
        # Create a New memory stream with the encrypted value. 
        $ms = new-Object IO.MemoryStream @(,$Encrypted)
        # Read the new memory stream and read it in the cryptology stream 
        $cs = new-Object Security.Cryptography.CryptoStream $ms,$d,"Read" 
        # Read the new decrypted stream 
        $sr = new-Object IO.StreamReader $cs 
        # Return from the function the stream 
        $ret += $sr.ReadToEnd()
        # Stops the stream
        $sr.Close() 
        # Stops the crypology stream 
        $cs.Close() 
        # Stops the memory stream 
        $ms.Close() 
        # Clears the RijndaelManaged Cryptology IV and Key 
        $r.Clear() 
    }
    return $ret
}

if ($backupPath -and $backupPath.Contains('/?'))
{ 
    ShowHelp
    return
}

Write-Host 'Starting the hosting restore process. Run with /? to see help.'
Write-Host ("Note: before running this script you may need to run:`r`n" + ' "net use /Y <backupPath> /user:<username> <password>"')
# argument parsing
if (!$backupPath)
{
    $backupPath = Read-Host "Please enter the name of the backup path (e.g. \\backupmachine\C$\backuplocation)"
}
if (!$password)
{
    $password = Read-Host "Please enter the password of the keys file" -AsSecureString
    $password = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($password))
}

$systemDrive = [System.Environment]::ExpandEnvironmentVariables('%systemdrive%\')
# Fetch restore data from remote machine
$localFeedLocation = ($systemDrive +'HostingOfflineFeed\')
$c = 0
do
{ 
    $c++
    "D" | xcopy /q /Y (Join-Path -Path $backupPath -ChildPath "HostingOfflineFeed") "$localFeedLocation" /E
} while ($c -lt 10 -and !$?)
# Install the IIS cmdlets
$dismLocation = Join-Path -Path $systemDrive -ChildPath 'Windows\System32\dism.exe'
& $dismLocation /online /enable-feature /featurename:IIS-ManagementScriptingTools /all
CreateFeedWebAppIfNeeded $localFeedLocation

Stop-Service ResourceMetering -ErrorAction SilentlyContinue
# install webpi
$wpi = (dir ($systemDrive + 'hostingofflinefeed\installers\HostingWebPlatformInstaller') -r -i 'wpi.msi').DirectoryName
if ($wpi.Count -gt 1)
{
    $wpi = $wpi[0]
}
$wpi = Join-Path -Path $wpi -ChildPath "wpi.msi"
msiexec /quiet /i $wpi
$offlineFeedUrl = 'https://localhost/HostingOfflineFeed/feeds/latest/WebSites0.9.0.xml'
InstallController $offlineFeedUrl
$keys = DecryptString (Join-Path -Path $backupPath -ChildPath 'encryptedkeys.txt') $password 'salt12345' 'init12345'
Stop-Service WebFarmService -ErrorAction SilentlyContinue
Add-PSSnapIn WebHostingSnapIn
# Restore the keys
# Keys are Base64 encoded
Set-ControllerConnectionString -ConnectionString (DecodeBase64($keys[0])) 3>$null
# Set-MeteringConnectionString -MeteringConnectionString (DecodeBase64($keys[1])) -ServerName (HostName)
Set-SymmetricKey -SymmetricKeyName SystemCore -SymmetricKey (DecodeBase64($keys[1])) 3>$null
Set-SymmetricKey -SymmetricKeyName SiteRuntime -SymmetricKey (DecodeBase64($keys[2])) 3>$null
Set-MeteringConnectionString -MeteringConnectionString ([Microsoft.Web.Hosting.SiteManager]::GetMeteringConnectionString()) -ServerName (HostName) 3>$null

Start-Service WebFarmService -ErrorAction SilentlyContinue

还原到名称或管理帐户不同的非文件服务器

如果必须将服务器(并非文件服务器或 SQL Server)还原到服务器名称或管理帐户与原始服务器不同的服务器,则必须:

  1. 导入网站模块

  2. 更新凭据

  3. 从场中删除旧服务器名称

  4. 将新服务器添加到适当的场

  1. 首先,在运行任何其他命令之前,导入网站模块:

    Import-Module WebSites
    

    现在,以管理员身份在控制器上运行命令 2-4。

  2. 如果角色< RoleType> 的凭据已更改,请针对每个已更改的凭据运行以下命令:

    Set-WebSitesConfig Credential -CredentialName <RoleType> Credential -UserName <RoleAdminUser> -Password <RoleAdminPassword>
    

    注意

    Set-WebSitesConfig命令中 RoleType> 的可能值为<:ManagementServer、FileServer、FrontEnd、Publisher 和 Worker。

  3. 对于不再使用的每个旧服务器名称 <OldName> ,请运行:

    Remove-WebSitesServer -Name <OldName>
    
  4. 对于角色 <RoleType> 的每个新服务器名称 <NewName>,请运行以下命令:

    New-WebSitesServer -Name <NewName> -ServerType <RoleType>
    

    注意

    New-WebSitesServer命令中 RoleType> 的可能值为<:ManagementServer、FileServer、LoadBalancer、Publisher 和 WebWorker。

示例

如果旧 Web 工作进程角色名为“OldWorker”,新 Web 工作进程角色名为“NewWorker”,并且已将 WebWorker 凭据更新为“WebWorkerAdmin”,则应运行:

Import-Module WebSites

Set-WebSitesConfig Credential -CredentialName WorkerCredential -UserName WebWorkerAdmin -Password $WebWorkerPassword

Remove-WebSitesServer -Name OldWorker

New-WebSitesServer -Name NewWorker -ServerType WebWorker

4. 在所有角色上运行修复

完成还原后,在所有角色上运行一次修复,并监视这些角色以确认其恢复正常。

另请参阅

备份 Microsoft Azure 包:网站
部署 Windows Azure 包:网站