還原 Windows Azure Pack: Web Sites

 

適用於: Windows Azure Pack

極力建議您還原到具有備份期間所用之相同名稱與系統管理帳戶的伺服器。還原要能成功,檔案伺服器與 SQL Server 的組態、使用者與權限必須和備份時完全相同。還原 Web Sites 服務時,請使用下列順序:

1.還原 SQL Server 資料庫

2.還原檔案伺服器

3.還原 Web Sites 控制器

4.對所有角色執行修復

您可以使用指令碼執行還原作業。以下將詳述這些步驟。

還原 SQL Server 代管資料庫、資源計量資料庫與 master 資料庫。SQL Server 的名稱必須和備份時所用的名稱相同。

下列指令碼範例僅供說明之用,實際上並不支援。您建立的指令碼必須以系統管理權限執行。

System_CAPS_note注意事項

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

檔案伺服器的名稱必須和備份時所用的名稱相同。請以下列順序還原檔案伺服器元件:

  1. 還原憑證共用

  2. 還原 WebSites 共用

  3. 視需要重新套用 ACL

  4. 對 WebSites 共用重新套用 FSRM 配額

以下提供兩個指令碼範例:一個會執行上述的步驟 a 至 c,一個會對 WebSites 共用重新套用 FSRM 配額。

下列範例指令碼包含上述的步驟 a 至 c (其不會還原 FSRM 配額)。此指令碼範例僅供說明之用,實際上並不支援。您建立的指令碼必須以系統管理權限執行。

System_CAPS_note注意事項

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 指令碼。此指令碼範例僅供說明之用,實際上並不支援。您建立的指令碼必須以系統管理權限執行。

System_CAPS_note注意事項

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

如果要還原 Web Sites 控制器,可以使用本節所示的 Restore.ps1 PowerShell 指令碼。

將 Restore.ps1 指令碼複製到 Web Sites 控制器,然後以系統管理權限執行下列命令:

net use /Y $backupLocation /user:$backupMachineAdmin $backupMachinePassword
.\Restore.ps1 $backupLocation $encryptionKey
System_CAPS_note注意事項

除非您在備份期間用了 $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 = 'http://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. 匯入 WebSites 模組

  2. 更新認證

  3. 從伺服陣列移除舊的伺服器名稱

  4. 在正確的伺服陣列中加入新的伺服器

  1. 首先,在執行任何其他命令之前,請先匯入 WebSites 模組:

    Import-Module WebSites
    

    以系統管理員身分在控制器上執行命令 2-4。

  2. 如果角色 <RoleType> 的認證已有變更,請對每一個變更的認證執行下列命令:

    Set-WebSitesConfig Credential -CredentialName <RoleType> Credential -UserName <RoleAdminUser> -Password <RoleAdminPassword>
    
    System_CAPS_note注意事項

    <RoleType> 在 Set-WebSitesConfig 命令中可有下列值:ManagementServer、FileServer、FrontEnd、Publisher 及 Worker。

  3. 對不再使用的舊伺服器名稱 <OldName> 執行:

    Remove-WebSitesServer -Name <OldName>
    
  4. <RoleType> 角色的每一個新伺服器名稱 <NewName> 執行:

    New-WebSitesServer -Name <NewName> -ServerType <RoleType>
    
    System_CAPS_note注意事項

    <RoleType> 在 New-WebSitesServer 命令中可有下列值:ManagementServer、FileServer、LoadBalancer、Publisher 及 WebWorker。

範例

如果您有名稱為 "OldWorker" 的舊 Web 背景工作角色及名稱為 "NewWorker" 的新 Web 背景工作角名,並已經將稱為 WebWorker 的認證更新為 "WebWorkerAdmin",您應執行:

Import-Module WebSites

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

Remove-WebSitesServer -Name OldWorker

New-WebSitesServer -Name NewWorker -ServerType WebWorker

完成還原之後,請對所有角色執行修復,並加以監視,確認其復原狀況。

顯示: