Windows: Robocopy mit VSS (Schattenkopie)

Robocopy ansich kann keine geöffneten Dateien kopieren. Seit Windows Server 2003 schaffen die Schattenkopien (VSS) abhilfe. Mit ein paar zusätzlichen Befehlen bzw. einem Skript kann man Robocopy und VSS zusammenbringen.

Folgendes Skript erstellt eine Schattenkopie, sichert diese mittels Robocopy und entfernt sie wieder. Robocopy arbeitet dabei mit Versionen. Eine Protokollierung und etwas Fehlerbehandlung ist ebenfalls enthalten. Ein Monitoring kann beispielsweise bei vorhandensein einer “error.txt” Alarm schlagen.

@echo off

cls

rem Evtl. vorhandenes altes Fehlerprotokoll entfernen

 if exist error.txt del /q error.txt

rem Protokoll erstellen

 echo %date% - %time% - Start > current.log

rem Konfiguration

 set DriveLetter=D:
 set ShadowCopyVolume=D:\CDP\ShadowCopyVolume

 set Source=%ShadowCopyVolume%\Share
 set Destination=D:\CDP\Backup\Share

 set NumberOfVersionsToKeep=10

rem Version.txt pruefen, falls diese nicht existiert, dann anlegen

 if not exist Version.txt echo %NumberOfVersionsToKeep% > Version.txt

rem Version auslesen und ggf. festlegen

 set /p Version=< Version.txt
 set Version=%Version: =%
 set /A Version=Version %% NumberOfVersionsToKeep + 1
 echo %Version% > Version.txt

rem Ziel-Ordner pruefen und ggf. anlegen

 if not exist "%Destination%\%Version%" mkdir "%Destination%\%Version%"

rem Schattenkopie erstellen

 echo %date% - %time% - Schattenkopie erstellen >> current.log

 vssadmin create shadow /for=%DriveLetter% > ShadowCopy.txt
 if %errorlevel% neq 0 echo error > error.txt & exit

rem Schattenkopie-Volumename auslesen

 type ShadowCopy.txt | find "Schattenkopie-Volumename:" > ShadowCopyName.txt
 set /p ShadowCopyName=< ShadowCopyName.txt set ShadowCopyName=%ShadowCopyName:~30%

rem Schattenkopiekennung auslesen
 type ShadowCopy.txt | find "Schattenkopiekennung:" > ShadowCopyID.txt
 set /p ShadowCopyID=< ShadowCopyID.txt
 set ShadowCopyID=%ShadowCopyID:~26%

rem Schattenkopie bereitstellen

 mklink /d "%ShadowCopyVolume%\" "%ShadowCopyName%\" > NUL
 
rem Robocopy ausfuehren

 echo %date% - %time% - Robocopy ausfuehren >> current.log

 robocopy "%Source%" "%Destination%\%Version%" /mir /r:0 /w:0 /xj /np /log:Logs\robocopy-%Version%.log
 if %errorlevel% gtr 1 echo Fehler bei der Ausfuehrung von Robocopy >> error.txt
 type Logs\robocopy-%Version%.log >> current.log

rem Schattenkopie-Bereitstellung aufheben

 echo %date% - %time% - Schattenkopie Bereitstellung aufheben und die Schattenkopie entfernen >> current.log

 rmdir "%ShadowCopyVolume%"
 
rem Schattenkopie loeschen

 vssadmin delete shadows /shadow=%ShadowCopyID% /quiet > NUL
 if %errorlevel% neq 0 echo Fehler beim Loeschen der Schattenkopie >> error.txt & exit
 
rem Aufraeumen

 del ShadowCopy.txt /q
 del ShadowCopyName.txt /q
 del ShadowCopyID.txt /q

echo %date% - %time% - Ende >> current.log

Den Schattenkopie-Teil des Skripts habe ich irgendwann 2016/2017 mal im Rahmen eines Feldversuchs geschrieben. Der Robocopy-Versionen-Teil stammt aus diesem Beitrag:

Windows: Robocopy-Backup mit Versionen

In dieser Fassung läuft das Skript bei einem Kunden auf einem Windows Server 2016 stündlich Montags bis Freitags von 08:00 bis 17:00 Uhr und stellt sozusagen ein Marke-Eigenbau-CDP für eine Freigabe dar.

Diese Maßnahme wurde notwendig, da immer wieder aus einer Branchen-Anwendung heraus aus versehen Dateien und Ordner gelöscht wurden.

Man kann zwar auch die regulären Schattenkopien häufiger laufen lassen, allerdings wird dann der Schattenkopie-Speicher entsprechend belastet. Da es allerdings nur darum geht einen Ordner öfter zu sichern erschien diese Lösung attraktiver. Mit dem Skript hat man außerdem die Option als Ziel ein anderes Laufwerk, ein NAS oder Server anzugeben.

Update 06.12.2021

Anbei eine Variante mit ShadowRun, mit dessen Hilfe das eigentliche Robocopy-Skript einfacher und (imho) die Ausführung zuverlässiger wird:

@echo off

rem Evtl. vorhandenes altes Fehlerprotokoll entfernen

 if exist error.txt del /q error.txt

rem Protokoll erstellen

 echo %date% - %time% - Start > current.log

rem Konfiguration

 set Source=V:\Share
 set Destination=D:\CDP\Backup\Share

 set NumberOfVersionsToKeep=10

rem Version.txt pruefen, falls diese nicht existiert, dann anlegen

 if not exist Version.txt echo %NumberOfVersionsToKeep% > Version.txt

rem Version auslesen und ggf. festlegen

 set /p Version=< Version.txt set Version=%Version: =% set /A Version=Version %% NumberOfVersionsToKeep + 1 echo %Version% > Version.txt

rem Ziel-Ordner pruefen und ggf. anlegen

 if not exist "%Destination%\%Version%" mkdir "%Destination%\%Version%"
 
rem Robocopy ausfuehren

 echo %date% - %time% - Robocopy ausfuehren >> current.log

 robocopy "%Source%" "%Destination%\%Version%" /mir /r:0 /w:0 /xj /np /log:Logs\robocopy-%Version%.log
 if %errorlevel% gtr 3 echo Fehler bei der Ausfuehrung von Robocopy - %errorlevel% >> error.txt
 type Logs\robocopy-%Version%.log >> current.log

rem Protkoll abschliessen

 echo %date% - %time% - Ende >> current.log

Dieses Skript wird dann mit

shadowrun.exe -env -mount -drive=V: -exec=CDP.cmd D:

aufgerufen. ShadowRun kümmert sich komplett um die Schattenkopie, das Robocopy-Skript muss nur noch vom bereitgestellten Laufwerk V: die Daten kopieren.

1 Kommentar

  1. Jens

    Hallo Andy,

    genau das, was ich schon lange gesucht habe.
    Kannst du das Skript noch mit der “Automatik” von Tom Stein (https://www.andysblog.de/windows-robocopy-backup-mit-versionen#comments) aktualisieren oder eine 2’te Version (am besten auch für “ROBOCOPY-BACKUP MIT VERSIONEN”) davon bereitstellen?

    Wäre echt super!
    Danke
    Jens

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

© 2024 Andy's Blog

Theme von Anders NorénHoch ↑