Jak używać kopii woluminu w tle do tworzenia kopii zapasowych


11

Plan polega na utworzeniu kopii w tle dość dużego woluminu z dużymi wejściami / wyjściami. Ma pojemność 350 GB i zawiera indeks pełnotekstowy oparty na systemie plików, zorganizowany w setki folderów i setki tysięcy maleńkich plików, które muszą być w spójnym stanie do pomyślnego przywrócenia.

Obecnie indeksator jest zatrzymany, zadanie tworzenia kopii zapasowej jest uruchamiane, a następnie indeksator jest ponownie uruchamiany. Powoduje to, że indeks jest niedostępny przez wiele godzin podczas tworzenia kopii zapasowej. Chciałbym tworzyć spójne kopie zapasowe za pomocą kopiowania w tle, najlepiej bez konieczności zatrzymywania indeksatora.

Tak więc włączyłem Shadow Copy dla tego woluminu i skonfigurowałem go do robienia migawki raz na noc, do innego woluminu.

Teraz jestem trochę zagubiony - jak mogę uzyskać dostęp do kopii w tle jako całości, aby móc wykonać kopię zapasową? Widzę dysk tylko do odczytu, który zawiera pliki takie, jakie były w czasie ostatniej migawki, ale może rzeczy działają zupełnie inaczej.

System operacyjny to Windows Server 2003 SP2, oprogramowanie do tworzenia kopii zapasowych to CommVault Galaxy 7.0.


EDYCJA : Zauważ, że - w międzyczasie - zostały utworzone dwie odpowiedzi, które implementują niezbędną funkcjonalność w postaci skryptu:


Czy galaktyka Commvault nie używa już VSS do utworzenia kopii zapasowej? Niejasno pamiętam, że Commvault był jednym z pierwszych dostawców rozwiązań do tworzenia kopii zapasowych opartych na VSS
Jim B

@Jim: Tak, ale tylko w przypadku zablokowanych plików na zasadzie „plik do pliku”. Potrzebuję wszystkich plików na dysku w spójnym stanie. Ale tak się nie stanie, chyba że a) indeksator nie uruchomi się lub b) Mam kopię migawkową, taką jak VSS.
Tomalak

VSS nie działa w ten sposób - jest to kopia w tle VOLUME. Jeśli używa VSS, jedyną różnicą jest to, że oprogramowanie do tworzenia kopii zapasowych trwałych snapów używa tymczasowych snapów. Przypuszczam, że aplikacja może wykonywać migawki usuwania dla poszczególnych plików, ale nie tylko kopie zapasowe byłyby niespójne, ale czas na wykonanie kopii zapasowej nawet domyślnej instalacji systemu Windows byłby rzędu dni. Zobacz msdn.microsoft.com/en-us/library/aa384589(VS.85).aspx, aby zobaczyć schemat działania przetwarzania VSS. Skontaktuję się z Commvault i sprawdzę, czy mogą upewnić się, że konfiguracja kopii zapasowej jest poprawna.
Jim B

Odpowiedzi:


10

Tak więc w duchu ponownego wynalezienia koła przedstawiam wam doskonały skrypt Tomalaka (patrz wyżej), ale całkowicie przepisany w Powershell !!! Głównym powodem, dla którego to zrobiłem, była ewangelizacja niesamowitych mocy Powershell, ale także dlatego, że nienawidzę vbscript całym ciałem.

Przeważnie jest to cecha identyczna, ale z różnych powodów zaimplementowałem niektóre rzeczy nieco inaczej. Wyniki debugowania są zdecydowanie bardziej szczegółowe.

Jedną bardzo ważną rzeczą do zapamiętania jest to, że ta wersja wykrywa wersję i bitowość systemu operacyjnego i wywołuje odpowiednią wersję vshadow.exe. Poniżej zamieszczam tabelę pokazującą, których wersji vshadow.exe należy użyć, gdzie je zdobyć i jak je nazwać.


Oto informacje o użyciu:

VssSnapshot.ps1

Description:
  Create, mount or delete a Volume Shadow Copy Service (VSS) Shadow Copy (snapshot)

Usage:
  VssSnapshot.ps1 Create -Target <Path> -Volume <Volume> [-Debug]
  VssSnapshot.ps1 Delete -Target <Path> [-Debug]

Paremeters:
  Create  - Create a snapshot for the specified volume and mount it at the specified target
  Delete  - Unmount and delete the snapshot mounted at the specified target
  -Target - The path (quoted string) of the snapshot mount point
  -Volume - The volume (drive letter) to snapshot
  -Debug  - Enable debug output (optional)

Examples:
  VssSnapshot.ps1 Create -Target D:\Backup\DriveC -Volume C
  - Create a snapshot of volume C and mount it at "D:\Backup\DriveC"

  VssSnapshot.ps1 Delete -Target D:\Backup\DriveC
  - Unmount and delete a snapshot mounted at "D:\Backup\DriveC"

Advanced:
  VssSnapshot.ps1 create -t "c:\vss mount\c" -v C -d
  - Create a snapshot of volume C and mount it at "C:\Vss Mount\C"
  - example mounts snapshot on source volume (C: --> C:)
  - example uses shortform parameter names
  - example uses quoted paths with whitespace
  - example includes debug output

Oto skrypt:

# VssSnapshot.ps1
# http://serverfault.com/questions/119120/how-to-use-a-volume-shadow-copy-to-make-backups/119592#119592

Param ([String]$Action, [String]$Target, [String]$Volume, [Switch]$Debug)
$ScriptCommandLine = $MyInvocation.Line
$vshadowPath = "."

# Functions
Function Check-Environment {
  Write-Dbg "Checking environment..."

  $UsageMsg = @'
VssSnapshot

Description:
  Create, mount or delete a Volume Shadow Copy Service (VSS) Shadow Copy (snapshot)

Usage:
  VssSnapshot.ps1 Create -Target <Path> -Volume <Volume> [-Debug]
  VssSnapshot.ps1 Delete -Target <Path> [-Debug]

Paremeters:
  Create  - Create a snapshot for the specified volume and mount it at the specified target
  Delete  - Unmount and delete the snapshot mounted at the specified target
  -Target - The path (quoted string) of the snapshot mount point
  -Volume - The volume (drive letter) to snapshot
  -Debug  - Enable debug output (optional)

Examples:
  VssSnapshot.ps1 Create -Target D:\Backup\DriveC -Volume C
  - Create a snapshot of volume C and mount it at "D:\Backup\DriveC"

  VssSnapshot.ps1 Delete -Target D:\Backup\DriveC
  - Unmount and delete a snapshot mounted at "D:\Backup\DriveC"

Advanced:
  VssSnapshot.ps1 create -t "c:\vss mount\c" -v C -d
  - Create a snapshot of volume C and mount it at "C:\Vss Mount\C"
  - example mounts snapshot on source volume (C: --> C:)
  - example uses shortform parameter names
  - example uses quoted paths with whitespace
  - example includes debug output
'@

  If ($Action -eq "Create" -And ($Target -And $Volume)) {
    $Script:Volume = (Get-PSDrive | Where-Object {$_.Name -eq ($Volume).Substring(0,1)}).Root
    If ($Volume -ne "") {
      Write-Dbg "Verified volume: $Volume"
    } Else {
      Write-Dbg "Cannot find the specified volume"
      Exit-Script "Cannot find the specified volume"
    }
    Write-Dbg "Argument check passed"
  } ElseIf ($Action -eq "Delete" -And $Target ) {
    Write-Dbg "Argument check passed"
  } Else {
    Write-Dbg "Invalid arguments: $ScriptCommandLine"
    Exit-Script "Invalid arguments`n`n$UsageMsg"
  }


  $WinVer = ((Get-WmiObject Win32_OperatingSystem).Version).Substring(0,3)
    Switch ($WinVer) {
    "5.2" {
      $vshadowExe = "vshadow_2003"
      $WinBit = ((Get-WmiObject Win32_Processor)[0]).AddressWidth
    }
    "6.0" {
      $vshadowExe = "vshadow_2008"
      $WinBit = (Get-WmiObject Win32_OperatingSystem).OSArchitecture
    }
    "6.1" {
      $vshadowExe = "vshadow_2008R2"
      $WinBit = (Get-WmiObject Win32_OperatingSystem).OSArchitecture
    }
    Default {
      Write-Dbg "Unable to determine OS version"
      Exit-Script "Unable to determine OS version"
    }
  }

  Switch ($WinBit) {
    {($_ -eq "32") -or ($_ -eq "32-bit")} {$vshadowExe += "_x86.exe"}
    {($_ -eq "64") -or ($_ -eq "64-bit")} {$vshadowExe += "_x64.exe"}
    Default {
      Write-Dbg "Unable to determine OS bitness"
      Exit-Script "Unable to determine OS bitness"
    }
  }

  $Script:vshadowExePath = Join-Path $vshadowPath $vshadowExe
  If (Test-Path $vshadowExePath) {
    Write-Dbg "Verified vshadow.exe: $vshadowExePath"
  } Else {
    Write-Dbg "Cannot find vshadow.exe: $vshadowExePath"
    Exit-Script "Cannot find vshadow.exe"
  }

  Write-Dbg "Environment ready"
}

Function Prepare-Target {
  Write-Log "Preparing target..."
  Write-Dbg "Preparing target $Target"


  If (!(Test-Path (Split-Path $Target -Parent))) {
  Write-Dbg "Target parent does not exist"
  Exit-Script "Invalid target $Target"
  }
  If ((Test-Path $Target)) {
    Write-Dbg "Target already exists"
    If (@(Get-ChildItem $Target).Count -eq 0) {
      Write-Dbg "Target is empty"
    } Else {
      Write-Dbg "Target is not empty"
      Exit-Script "Target contains files/folders"
    }
  } Else {
    Write-Dbg "Target does not exist. Prompting user..."
    $PromptYes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", "Create target folder"
    $PromptNo = New-Object System.Management.Automation.Host.ChoiceDescription "&No", "Do not create target folder"
    $PromptOptions = [System.Management.Automation.Host.ChoiceDescription[]]($PromptYes, $PromptNo)
    $PromptResult = $Host.UI.PromptForChoice("Create folder", "The target folder `"$target`" does not exist.`nWould you like to create the folder?", $PromptOptions, 0) 
    Switch ($PromptResult) {
      0 {
        Write-Dbg "User Accepted. Creating target..."
        $Null = New-Item -Path (Split-Path $Target -Parent) -Name (Split-Path $Target -Leaf) -ItemType "Directory"
      }
      1 {
        Write-Dbg "User declined. Exiting..."
        Exit-Script "Target does not exist"
      }
    }
  }
  Write-Log "Target ""$Target"" ready"
  Write-Dbg """$Target"" ready"
}

Function Create-Snapshot {
  Write-Log "Creating snapshot..."
  Write-Dbg "Creating snapshot of $Volume"
  $Cmd = "$vshadowExePath -p $Volume"
  $CmdResult = Run-Command $Cmd -AsString

  Write-Dbg "Snapshot created successfully"

  $SnapshotID = $CmdResult -Match 'SNAPSHOT ID = (\{[^}]{36}\})'
  If ($SnapshotID) {
    $SnapshotID = $Matches[1]
    Write-Dbg "SnapshotID: $SnapshotID"
    Write-Log "Snapshot $SnapshotID created"
  } Else {
    Write-Dbg "Unable to determine SnapshotID"
    Exit-Script "Unable to determine SnapshotID"
  }

  Return $SnapshotID
}

Function Mount-Snapshot ($SnapshotID) {
  Write-Log "Mounting snapshot..."
  Write-Dbg "Mounting $SnapshotID at ""$Target"""

  $Cmd = "$vshadowExePath `"-el=$SnapshotId,$Target`"" #Must use escaped quotes because Invoke-Expression gets all weird about curly braces
  $CmdResult = Run-Command $Cmd

  Write-Log "Snapshot $SnapshotID mounted at target ""$Target"""
  Write-Dbg "$SnapshotID mounted at ""$Target"""
}

Function Delete-Snapshot {
  Write-Log "Deleting snapshot..."
  Write-Dbg "Deleting snapshot at target ""$Target"""

  $SnapshotID = Get-SnapshotIdbyTarget

  $Cmd = "$vshadowExePath `"-ds=$SnapshotId`""
  $CmdResult = Run-Command $Cmd

  Write-Log "Snapshot $SnapshotID deleted at target ""$Target"""
  Write-Dbg "$SnapshotID deleted at ""$Target"""
}

Function Get-SnapshotIdbyTarget {
  Write-Dbg "Finding SnapshotID for $Target"

  $Cmd = "$vshadowExePath -q"
  $CmdResult = Run-Command $Cmd -AsString

  $TargetRegEx = '(?i)' + $Target.Replace('\','\\') + '\\?\r'
  $Snapshots = ($CmdResult.Split('*')) -Match $TargetRegEx | Out-String

  If ($Snapshots) {
    $Null = $Snapshots -Match '(\{[^}]{36}\})'
    $SnapshotID = $Matches[0]
  } Else {
    Write-Dbg "Unable to determine SnapshotID for target $Target"
    Exit-Script "Unable to determine SnapshotID"
  }  

  Write-Dbg "SnapshotID: $SnapshotID"

  Return $SnapshotID
}

Function Run-Command ([String]$Cmd, [Switch]$AsString=$False, [Switch]$AsArray=$False) {
  Write-Dbg "Running: $Cmd"

  $CmdOutputArray = Invoke-Expression $Cmd
  $CmdOutputString = $CmdOutputArray | Out-String
  $CmdErrorCode = $LASTEXITCODE

  If ($CmdErrorCode -eq 0 ) {
    Write-Dbg "Command successful. Exit code: $CmdErrorCode"
    Write-Dbg $CmdOutputString
  } Else {
    Write-Dbg "Command failed. Exit code: $CmdErrorCode"
    Write-Dbg $CmdOutputString
    Exit-Script "Command failed. Exit code: $CmdErrorCode"
  }

  If (!($AsString -or $AsArray)) {
    Return $CmdErrorCode
  } ElseIf ($AsString) {
    Return $CmdOutputString
  } ElseIf ($AsArray) {
    Return $CmdOutputArray
  }
}

Function Write-Msg ([String]$Message) {
  If ($Message -ne "") {
    Write-Host $Message
  }
}

Function Write-Log ([String]$Message) {
  Write-Msg "[$(Get-Date -Format G)] $Message"
}

Function Write-Dbg ([String]$Message) {
  If ($Debug) {
    Write-Msg ("-" * 80)
    Write-Msg "[DEBUG] $Message"
    Write-Msg ("-" * 80)
  }
}

Function Exit-Script ([String]$Message) {
  If ($Message -ne "") {
    Write-Msg "`n[FATAL ERROR] $Message`n"
  }
  Exit 1
}

# Main
Write-Log "VssSnapshot started"
Check-Environment

Switch ($Action) {
  "Create" {
    Prepare-Target
    $SnapshotID = Create-Snapshot
    Mount-Snapshot $SnapshotID
  }
  "Delete" {
    Delete-Snapshot
  }
}

Write-Log "VssSnapshot finished"

Oto wersje vshadow.exe do użycia:

  1. Windows 2003 / 2003R2
    • SDK usługi kopiowania woluminów w tle 7.2
    • x86: C: \ Program Files \ Microsoft \ VSSSDK72 \ TestApps \ vshadow \ bin \ release-server \ vshadow.exe
      • Zmień nazwę na: vshadow_2003_x86.exe
    • x64: Nie udało mi się znaleźć wersji xsh programu vshadow.exe dla systemu Windows 2003 x64
  2. Windows 2008
    • Zestaw Windows SDK dla systemu Windows Server 2008 i .NET Framework 3.5
    • x86: C: \ Program Files \ Microsoft SDKs \ Windows \ v6.1 \ Bin \ vsstools \ vshadow.exe
      • Zmień nazwę na: vshadow_2008_x86.exe
    • x64: C: \ Program Files \ Microsoft SDKs \ Windows \ v6.1 \ Bin \ x64 \ vsstools \ vshadow.exe
      • Zmień nazwę na: vshadow_2008_x64.exe
  3. Windows 2008 R2
    • Microsoft Windows SDK dla Windows 7 i .NET Framework 4
    • x86: C: \ Program Files (x86) \ Microsoft SDKs \ Windows \ v7.0A \ Bin \ vsstools \ vshadow.exe
      • Zmień nazwę na: vshadow_2008R2_x86.exe
    • x64: C: \ Program Files (x86) \ Microsoft SDKs \ Windows \ v7.0A \ Bin \ x64 \ vsstools \ vshadow.exe
      • Zmień nazwę na: vshadow_2008R2_x64.exe

2
btw ... Udało mi się to wdrożyć jako część naszego rozwiązania do tworzenia kopii zapasowych, używając Arcserve jako otwartej kopii zapasowej biednego człowieka. To lepsze niż płacenie 800 $ za serwer za licencję agenta. Jeśli ktoś jest zainteresowany, opublikuję tutaj.
John Homer

+1 To jest całkiem niesamowite. Dziękujemy za poświęcenie czasu na przesłanie tego do ps (pomimo twojej nienawiści do VBS) i za udostępnienie go tutaj. Mam nadzieję, że więcej osób uzna to za przydatne, ponieważ zdecydowanie zasługuje na więcej niż jeden głos w górę.
Tomalak

9

Więc… Pracowałem nad małym VBScript, który może:

  • rób trwałe migawki VSS
  • zamontuj je w folderze (z którego możesz następnie wykonać kopię zapasową plików)
  • odmontować migawki VSS

Opiera się na vshadow.exe( dokumentacji ) części SDK 7.2 usługi kopiowania woluminów w tle, dostępnej w firmie Microsoft. Pracowałem z tą wersją: „ VSHADOW.EXE 2.2 - przykładowy klient Volume Shadow Copy, Copyright (C) 2005 Microsoft Corporation ”.

Zasadniczo jest to miłe małe opakowanie wokół tych czterech poleceń vshadow:

vshadow.exe -q - wyświetla listę wszystkich kopii w tle w systemie
vshadow.exe -p {lista woluminów} - Zarządza trwałymi kopiami w tle
vshadow.exe -el = {SnapID}, reż - Ujawnij kopię w tle jako punkt montowania
vshadow.exe -ds = {SnapID} - Usuwa tę kopię w tle

Oto jego ekran pomocy:

Narzędzie tworzenia / montowania migawek VSS

Stosowanie:
cscript / nologo VssSnapshot.vbs / target: path {/ volume: X | / unmount} [/ debug]

/ wolumin - litera woluminu do migawki
/ target - ścieżka (bezwzględna lub względna) do zamontowania migawki
/ debug - przełącznik na wyjściu debugowania

Przykłady:
cscript / nologo VssSnapshot.vbs / target: C: \ Backup \ DriveD / volume: D
cscript / nologo VssSnapshot.vbs / target: C: \ Backup \ DriveD / unmount

Wskazówka: Nie trzeba odmontowywać przed zrobieniem nowej migawki.

Oto przykładowe dane wyjściowe:

C: \ VssSnapshot> cscript / nologo VssSnapshot.vbs / target: MountPoints \ E / volume: E
05/03/2010 17:13:04 przygotowanie punktu montowania VSS ...
05/03/2010 17:13:04 punkt montowania przygotowany w: C: \ VssSnapshot \ MountPoints \ E
05/03/2010 17:13:04 tworzenie migawki VSS dla woluminu: E
05/03/2010 17:13:08 migawka utworzona z identyfikatorem: {4ed3a907-c66f-4b20-bda0-9dcda3b667ec}
05/03/2010 17:13:08 Migawka VSS została pomyślnie zainstalowana
05.03.2010 17:13:08 zakończone

C: \ VssSnapshot> cscript / nologo VssSnapshot.vbs / target: MountPoints \ E / unmount
05/03/2010 17:13:35 przygotowanie punktu montowania VSS ...
05/03/2010 17:13:36 nic innego do roboty
05.03.2010 17:13:36 zakończone

A oto sam skrypt. Obowiązuje zwykłe zrzeczenie się: Oprogramowanie jest dostarczane w stanie, w jakim się znajduje, nie udzielam gwarancji, używam na własne ryzyko, jeśli coś złamie, jedyną winną jest ty sam. Jednak przetestowałem go dość dokładnie i działa dla mnie dobrze. Powiadom mnie o wszelkich błędach za pomocą poniższych komentarzy.

''# VssSnapshot.vbs
''# http://serverfault.com/questions/119120/how-to-use-a-volume-shadow-copy-to-make-backups/119592#119592
Option Explicit

Dim fso: Set fso = CreateObject("Scripting.FileSystemObject")

''# -- MAIN SCRIPT -------------------------------------------
Dim args, snapshotId, targetPath, success
Set args = WScript.Arguments.Named
CheckEnvironment

Log "preparing VSS mount point..."
targetPath = PrepareVssMountPoint(args("target"))

If args.Exists("unmount") Then
  Log "nothing else to do"
ElseIf targetPath <> vbEmpty Then
  Log "mount point prepared at: " & targetPath
  Log "creating VSS snapshot for volume: " & args("volume")
  snapshotId = CreateVssSnapshot(args("volume"))

  If snapshotId <> vbEmpty Then
    Log "snapshot created with ID: " & snapshotId
    success = MountVssSnapshot(snapshotId, targetPath)
    If success Then
      Log "VSS snapshot mounted sucessfully"
    Else
      Die "failed to mount snapshot"
    End If
  Else
    Die "failed to create snapshot"
  End If
Else
  Die "failed to prepare mount point"
End If

Log "finished"

''# -- FUNCTIONS ---------------------------------------------
Function PrepareVssMountPoint(target) ''# As String
  Dim cmd, result, outArray
  Dim path, snapshot, snapshotId
  Dim re, matches, match

  PrepareVssMountPoint = VbEmpty
  target = fso.GetAbsolutePathName(target)

  If Not fso.FolderExists(fso.GetParentFolderName(target)) Then 
    Die "Invalid mount point: " & target
  End If

  ''# create or unmount (=delete existing snapshot) mountpoint
  If Not fso.FolderExists(target) Then
    If Not args.Exists("unmount") Then fso.CreateFolder target
  Else
    Set re = New RegExp
    re.MultiLine = False
    re.Pattern = "- Exposed locally as: ([^\r\n]*)"

    cmd = "vshadow -q"
    result = RunCommand(cmd, false)
    outarray = Split(result, "*")

    For Each snapshot In outArray
      snapshotId = ParseSnapshotId(snapshot)
      If snapshotId <> vbEmpty Then
        Set matches = re.Execute(snapshot)
        If matches.Count = 1 Then
          path = Trim(matches(0).SubMatches(0))
          If fso.GetAbsolutePathName(path) = target Then
            cmd = "vshadow -ds=" & snapshotId
            RunCommand cmd, true
            Exit For
          End If
        End If
      End If
    Next

    If args.Exists("unmount") Then fso.DeleteFolder target
  End If

  PrepareVssMountPoint = target
End Function

Function CreateVssSnapshot(volume) ''# As String
  Dim cmd, result

  If Not fso.DriveExists(volume) Then
    Die "Drive " & volume & " does not exist."
  End If

  cmd = "vshadow -p " & Replace(UCase(volume), ":", "") & ":"
  result = RunCommand(cmd, false)
  CreateVssSnapshot = ParseSnapshotId(result)
End Function

Function MountVssSnapshot(snapshotId, target) ''# As Boolean
  Dim cmd, result

  If fso.FolderExists(targetPath) Then
    cmd = "vshadow -el=" & snapshotId & "," & targetPath
    result = RunCommand(cmd, true)
  Else
    Die "Mountpoint does not exist: " & target
  End If

  MountVssSnapshot = (result = "0")
End Function

Function ParseSnapshotId(output) ''# As String
  Dim re, matches, match

  Set re = New RegExp
  re.Pattern = "SNAPSHOT ID = (\{[^}]{36}\})"
  Set matches = re.Execute(output)

  If matches.Count = 1 Then
    ParseSnapshotId = matches(0).SubMatches(0)
  Else
    ParseSnapshotId = vbEmpty
  End If
End Function

Function RunCommand(cmd, exitCodeOnly) ''# As String
  Dim shell, process, output

  Dbg "Running: " & cmd

  Set shell = CreateObject("WScript.Shell")

  On Error Resume Next
  Set process = Shell.Exec(cmd)
  If Err.Number <> 0 Then
    Die Hex(Err.Number) & " - " & Err.Description
  End If
  On Error GoTo 0

  Do While process.Status = 0
    WScript.Sleep 100
  Loop
  output = Process.StdOut.ReadAll

  If process.ExitCode = 0 Then 
    Dbg "OK"
    Dbg output
  Else
    Dbg "Failed with ERRORLEVEL " & process.ExitCode
    Dbg output
    If Not process.StdErr.AtEndOfStream Then 
      Dbg process.StdErr.ReadAll
    End If
  End If  

  If exitCodeOnly Then
    Runcommand = process.ExitCode
  Else
    RunCommand = output
  End If
End Function

Sub CheckEnvironment
  Dim argsOk

  If LCase(fso.GetFileName(WScript.FullName)) <> "cscript.exe" Then
    Say "Please execute me on the command line via cscript.exe!"
    Die ""
  End If

  argsOk = args.Exists("target")
  argsOk = argsOk And (args.Exists("volume") Or args.Exists("unmount"))

  If Not argsOk Then
    Say "VSS Snapshot Create/Mount Tool" & vbNewLine & _
        vbNewLine & _
        "Usage: " & vbNewLine & _
        "cscript /nologo " & fso.GetFileName(WScript.ScriptFullName) & _
          " /target:path { /volume:X | /unmount } [/debug]" & _
        vbNewLine & vbNewLine & _
        "/volume  - drive letter of the volume to snapshot" & _
        vbNewLine & _
        "/target  - the path (absolute or relative) to mount the snapshot to" & _
        vbNewLine & _
        "/debug   - swich on debug output" & _
        vbNewLine & vbNewLine & _
        "Examples: " & vbNewLine & _
        "cscript /nologo " & fso.GetFileName(WScript.ScriptFullName) & _
          " /target:C:\Backup\DriveD /volume:D" &  vbNewLine & _
        "cscript /nologo " & fso.GetFileName(WScript.ScriptFullName) & _
          " /target:C:\Backup\DriveD /unmount" & _
        vbNewLine & vbNewLine & _
        "Hint: No need to unmount before taking a new snapshot." & vbNewLine

    Die ""
  End If
End Sub

Sub Say(message)
  If message <> "" Then WScript.Echo message
End Sub

Sub Log(message)
  Say FormatDateTime(Now()) & " " & message
End Sub

Sub Dbg(message)
  If args.Exists("debug") Then 
    Say String(75, "-")
    Say "DEBUG: " & message
  End If
End Sub

Sub Die(message)
  If message <> "" Then Say "FATAL ERROR: " & message
  WScript.Quit 1
End Sub

Mam nadzieję, że to komuś pomoże. Używaj go zgodnie z CC-BY-SA . Proszę tylko o pozostawienie nienaruszonego linku, który wskazuje tutaj.


I czy wykonałeś pełne odzyskiwanie danych po awarii z nowego systemu? Tworzenie kopii zapasowej jest łatwe. Przywracanie z niego czasami nie tak bardzo.
Rob Moir

@Robert: Dotyczy to zarówno tego podejścia, jak i każdego innego rodzaju kopii zapasowej. Zajmę się tym, jak tylko to się skończy.
Tomalak,

1
+1 za nieakceptowanie odpowiedzi „nie” i przeforsowanie, aby udowodnić, że istnieje realne rozwiązanie, które niektórzy inni plakaty mogliby zaoferować zamiast odpowiedzi, że nie da się tego zrobić.
Chris Magnuson

Czy to w końcu umożliwiło odtworzenie kopii zapasowej? Czy można go używać z Robocopy?
Kev

1
@Kev: Tak, ale zdecydowanie powinieneś sam to przetestować. Jeśli znajdziesz problem, powiedz mi tutaj. Możesz użyć Robocopy lub innego preferowanego narzędzia, zamontowany wolumin zachowuje się jak normalny dysk.
Tomalak,

6
  1. Użyj polecenia, vssadmin list shadowsaby wyświetlić listę wszystkich dostępnych kopii w tle. Otrzymasz taki wynik ...
C: \> cienie listy vssadmin
vssadmin 1.1 - administracyjne narzędzie wiersza polecenia usługi kopiowania woluminów w tle
(C) Copyright 2001 Microsoft Corp.

Zawartość identyfikatora zestawu kopii w tle: {b6f6fb45-bedd-4b77-8f51-14292ee921f3}
   Zawiera 1 kopię w tle w czasie tworzenia: 25.09.2016 12:14:23 PM
      Identyfikator kopiowania w tle: {321930d4-0442-4cc6-b2aa-ec47f21d0eb1}
         Oryginalny tom: (C:) \\? \ Tom {ad1dd231-1200-11de-b1df-806e6f6e6963} \
         Wolumin kopiowania w tle: \\? \ GLOBALROOT \ Device \ HarddiskVolumeShadowCopy68
         Pochodząca maszyna: joshweb.josh.com
         Maszyna serwisowa: joshweb.josh.com
         Dostawca: „Microsoft Software Shadow Copy dostawca 1.0”
         Wpisz: ClientAccessible
         Atrybuty: Trwały, Dostępny dla klienta, Bez automatycznego wydania, Bez autorów, Różnicowy

Zawartość identyfikatora zestawu kopii w tle: {c4fd8646-57b3-4b39-be75-47dc8e7f881d}
   Zawiera 1 kopię w tle w czasie tworzenia: 8/25/2016 7:00:18 AM
      Identyfikator kopiowania w tle: {fa5da100-5d90-493c-89b1-5c27874a23c6}
         Oryginalny tom: (E:) \\? \ Tom {4ec17949-12b6-11de-8872-00235428b661} \
         Wolumin kopiowania w tle: \\? \ GLOBALROOT \ Device \ HarddiskVolumeShadowCopy3
         Pochodząca maszyna: joshweb.josh.com
         Maszyna serwisowa: joshweb.josh.com
         Dostawca: „Microsoft Software Shadow Copy dostawca 1.0”
         Wpisz: ClientAccessible
         Atrybuty: Trwały, Dostępny dla klienta, Bez automatycznego wydania, Bez autorów, Różnicowy

DO:\
  1. Zanotuj Shadow Copy Volumenazwę żądanej kopii w tle (najłatwiejsza do schowka).

  2. Zamontuj kopię w tle

W systemie Windows 2003 ...

Musisz pobrać narzędzia zestawu zasobów dla 2003 roku, jeśli jeszcze go nie masz.

Wpisz polecenie ...

linkd c: \ shadow \\? \ GLOBALROOT \ Device \ HarddiskVolumeShadowCopy69 \

... gdzie c:\shadowjest ścieżka, w której ma się pojawiać kopia w tle, i \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy69nazwa, którą skopiowałeś powyżej. Pamiętaj, że musisz dodać ukośnik odwrotny na końcu nazwy kopii w tle!

W systemie Windows 2008 i nowszych ...

Wpisz polecenie ...

mklink c: \ shadow \\? \ GLOBALROOT \ Device \ HarddiskVolumeShadowCopy69 \

... gdzie c:\shadowjest ścieżka, w której ma się pojawiać kopia w tle, i \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy69nazwa, którą skopiowałeś powyżej. Pamiętaj, że musisz dodać ukośnik odwrotny na końcu nazwy kopii w tle!

  1. Użyj dowolnego narzędzia (w tym Eksploratora Windows lub XCOPY), aby uzyskać dostęp do plików c:\shadow.

Więc ... aby to zautomatyzować, musisz przeanalizować dane wyjściowe list shadows?
Kev,

Podoba mi się ta odpowiedź, ale nie zadziałało to dla mnie podczas montowania \\? \ GLOBALROOT \ Device \ HarddiskVolumeShadowCopy_n_ Zamiast tego użyłem pliku odniesienia i czasu migawki z udziału głównego (na przykład C $) mklink / DD: \ TempMount \\ localhost \ C $ \ @ GMT-2011.01.01-06.00.08 - niestety jest to prawdopodobnie proces ręczny, ale w nagłych przypadkach działa.
Lewis

2

Nie rozumiesz, jak VSS współpracuje z systemem plików (jak działa z bazami danych, jest zupełnie inny). W systemie plików VSS służy do implementacji funkcji „Poprzednie wersje”, która służy wyłącznie do tworzenia migawek zmian w plikach i folderach we wcześniej określonych punktach w celu odzyskania za pomocą karty Poprzednie wersje w klientach. Zmiany te są następnie łączone z danymi w woluminie w celu zbudowania zestawu odzyskiwania. Jest więc zależny od tego, czy oryginalny wolumin nadal tam jest w celu przeprowadzenia odzyskiwania, co innymi słowy jest bezużyteczne do celów prawidłowego tworzenia kopii zapasowych i przywracania.

Myślę, że musisz wycofać się z tego, jak chcesz to zrobić, i jeszcze raz pomyśleć o tym, co chcesz zrobić.

350 GB danych to naprawdę niewiele, i mogę się założyć, że procent tego, co jest aktywnie wykorzystywane na co dzień, jest dość niski. Czy rozważałeś tworzenie nocnych różnicowych kopii zapasowych z pełnymi kopiami zapasowymi tylko w weekendy? Lub przy użyciu zaplanowanej replikacji systemu plików DFS do alternatywnego magazynu w celu uzyskania „migawki” (która jest następnie tworzona)


Liczba zmian wynosi około 60 GB dziennie, jeśli chodzi o różnicową kopię zapasową. Regularne przerwy w świadczeniu usług są wystarczająco długie, aby czasami denerwować użytkowników, może „godziny” były nieco przesadzone. Chodzi mi o to - kiedy tworzę kopię zapasową migawki VSS na taśmie, mam wszystko, czego potrzebuję, aby pomyślnie przywrócić dane. Pracuję nad skryptem, który robi to, czego potrzebuję obecnie, wygląda całkiem obiecująco. Po zakończeniu opublikuję go tutaj.
Tomalak,

@mh: Wysłałem swój skrypt. Stał się nieco większy niż zamierzałem, ale działa dobrze i jest wygodny w użyciu. Spójrz! :)
Tomalak

1
-1 Źle zinterpretowałeś pytanie. Nie próbuje używać VSS jako źródła kopii zapasowej, próbuje go użyć do utworzenia migawki swoich plików w czasie tylko do odczytu, którą następnie może przenieść na napęd taśmowy lub inny nośnik. Nie rozumiem, dlaczego nie jest to doskonały przypadek użycia tej technologii?
Chris Magnuson

2

Mam nadzieję, że tego właśnie chcesz:

diskshadow -s vssbackup.cfg

vssbackup.cfg:

set context persistent
set metadata E:\backup\result.cab
set verbose on
begin backup
     add volume C: alias ConfigVolume
     create
     EXPOSE %ConfigVolume% Y:
     # Y is your VSS drive
     # run your backup script here
     delete shadows exposed Y:
end backup

diskshadow to Windows Server 2008, AFAIK.
Tomalak,

@jackbean: Stworzyłem skrypt, który robi coś podobnego dla Windows 2003, ponieważ do tej pory nie znalazłem niczego przekonującego w Internecie. Zobacz moją odpowiedź.
Tomalak,

przepraszam, wiem, że to za rok 2008, ale jakoś miałem to w głowie, masz 2008 R2.
jackbean

0

Korzystając z interfejsu API VSS, można wykonać „migawkę” woluminu. Następnie musisz zamontować tę migawkę, aby z niej skopiować. Znam martwy produkt, który wykorzystywał tę technikę do replikacji danych, mimo że pliki są otwierane wyłącznie przez inne procesy w systemie plików na żywo. Można zadać ważne pytania dotyczące tego, czy pliki w migawce VSS są spójne, jeśli są zapisywane przez aplikacje, które nie są zintegrowane z interfejsami API VSS. Mogą istnieć inne produkty, które oferują podobne możliwości.


@Fred: Tak właśnie zrobiłem, używając VBScript i narzędzia wiersza polecenia Microsoft. Zobacz moją odpowiedź.
Tomalak,

-1

Krótka odpowiedź: nie możesz.

Nieco dłuższa odpowiedź: z usługi kopiowania w tle można korzystać programowo poprzez interfejs API, aby umożliwić tworzenie kopii zapasowych otwartych plików, ale usługa nie tworzy pełnych migawek systemu, tylko migawki częściowe.


2
Nie wierzę, że to niemożliwe. Nie potrzebuję pełnej „migawki systemu”, tylko kopii pojedynczego woluminu w określonym momencie. Z grubsza wiem, w jaki sposób kopiowanie w tle działa wewnętrznie, i wiem, że można go używać do tworzenia kopii zapasowych używanych plików (wybitnymi przykładami w sieci są bazy danych Exchange lub SQL).
Tomalak,

1
@John: Okazuje się, że mogę. Zobacz moją odpowiedź!
Tomalak

Widzę, że używasz interfejsu API tak samo, jak oprogramowanie do tworzenia kopii zapasowych. Tak więc podczas korzystania z usługi VSS jest zupełnie inaczej niż przy użyciu Volume Shadow Copy. Niemniej jednak, jeśli robi to, co chcesz, to wszystko jest naprawdę ważne. Dobra robota.
John Gardeniers,

1
Twoja krótka i długa odpowiedź jest błędna, a określenie „Volume Shadow Copy” powinno wystarczyć do wskazania tego, czego szukał użytkownik, nawet jeśli termin ten jest nieco niejednoznaczny. en.wikipedia.org/wiki/Shadow_Copy
Chris Magnuson

1
Może masz rację. Nie rozumiem, w jaki sposób twoja odpowiedź „Nie możesz” jest poprawna, gdy PO znalazł sposób na zrobienie tego, co opisał. Twoja długa odpowiedź nie ma związku z zadanym pytaniem, ponieważ chociaż interfejs API pozwala tylko na „częściowe migawki”, nadal możesz zamontować reprezentację całego wolumenu w danym momencie i wykonać kopię zapasową zgodnie z życzeniem OP. Jeśli mógłbyś wyjaśnić, co masz na myśli w swoim oryginalnym poście, aby był edytowany w celu odniesienia się do tego, co udało się osiągnąć PO, chętnie usunę głos negatywny i dodam aktualizację, jeśli informacje są istotne.
Chris Magnuson
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.