Делаем резервные копии виртуальных дисков Hyper-V без специального софта средствами PowerShell.
Создаем скрипт powershell с таким содержимым
$Destination="D:\Backup" #место хранения копий $Versions="2" #количество хранимых копий $BackupDirs="D:\Hyper-V\Virtual Hard Disks" #место расположения данных для копирования $Log="Log.txt" #имя лог-файла $LoggingLevel="1" #уровень логирования - 1=smart, 3=Heavy #настройки E-mail $SMTPServer = "smtp.domain.ru" $SMTPPort = "587" $Username = "support@domain.ru" $Password = "emailpassword" $to = "admin@domain.ru" $subject = "DOMAIN.ru VM-HDD Backup Log" $body = "Файл лога резервного копирования во вложении" #STOP-no changes from here #Settings - do not change anything from here $Backupdir=$Destination +"\Backup-"+ (Get-Date -format yyyy-MM-dd)+"-"+(Get-Random -Maximum 100000)+"\" $Items=0 $Count=0 $ErrorCount=0 $StartDate=Get-Date #-format dd.MM.yyyy-HH:mm:ss #FUNCTION #Logging Function Logging ($State, $Message) { $Datum=Get-Date -format dd.MM.yyyy-HH:mm:ss if (!(Test-Path -Path $Log)) { New-Item -Path $Log -ItemType File | Out-Null } $Text="$Datum - $State"+":"+" $Message" if ($LoggingLevel -eq "1" -and $Message -notmatch "was copied") {Write-Host $Text} elseif ($LoggingLevel -eq "3" -and $Message -match "was copied") {Write-Host $Text} add-Content -Path $Log -Value $Text } Logging "INFO" "----------------------" Logging "INFO" "Start the Script" #Create Backupdir Function Create-Backupdir { Logging "INFO" "Create Backupdir $Backupdir" New-Item -Path $Backupdir -ItemType Directory | Out-Null Logging "INFO" "Move Log file to $Backupdir" Move-Item -Path $Log -Destination $Backupdir Set-Location $Backupdir Logging "INFO" "Continue with Log File at $Backupdir" } #Delete Backupdir Function Delete-Backupdir { $Folder=Get-ChildItem $Destination | where {$_.Attributes -eq "Directory"} | Sort-Object -Property $_.LastWriteTime -Descending:$false | Select-Object -First 1 Logging "INFO" "Remove Dir: $Folder" $Folder.FullName | Remove-Item -Recurse -Force } #Check if Backupdirs and Destination is available function Check-Dir { Logging "INFO" "Check if BackupDir and Destination exists" if (!(Test-Path $BackupDirs)) { return $false Logging "Error" "$BackupDirs does not exist" } if (!(Test-Path $Destination)) { return $false Logging "Error" "$Destination does not exist" } } #Save all the Files Function Make-Backup { Logging "INFO" "Started the Backup" $Files=@() $SumMB=0 $SumItems=0 $SumCount=0 $colItems=0 Logging "INFO" "Count all files and create the Top Level Directories" foreach ($Backup in $BackupDirs) { $colItems = (Get-ChildItem $Backup -recurse | Where-Object {$_.mode -notmatch "h"} | Measure-Object -property length -sum) $Items=0 $FilesCount += Get-ChildItem $Backup -Recurse | Where-Object {$_.mode -notmatch "h"} Copy-Item -Path $Backup -Destination $Backupdir -Force -ErrorAction SilentlyContinue $SumMB+=$colItems.Sum.ToString() $SumItems+=$colItems.Count } $TotalMB="{0:N2}" -f ($SumMB / 1MB) + " MB of Files" Logging "INFO" "There are $SumItems Files with $TotalMB to copy" foreach ($Backup in $BackupDirs) { $Index=$Backup.LastIndexOf("\") $SplitBackup=$Backup.substring(0,$Index) $Files = Get-ChildItem $Backup -Recurse | Where-Object {$_.mode -notmatch "h"} foreach ($File in $Files) { $restpath = $file.fullname.replace($SplitBackup,"") try { Copy-Item $file.fullname $($Backupdir+$restpath) -Force -ErrorAction SilentlyContinue |Out-Null Logging "INFO" "$file was copied" } catch { $ErrorCount++ Logging "ERROR" "$file returned an error an was not copied" } $Items += (Get-item $file.fullname).Length $status = "Copy file {0} of {1} and copied {3} MB of {4} MB: {2}" -f $count,$SumItems,$file.Name,("{0:N2}" -f ($Items / 1MB)).ToString(),("{0:N2}" -f ($SumMB / 1MB)).ToString() $Index=[array]::IndexOf($BackupDirs,$Backup)+1 $Text="Copy data Location {0} of {1}" -f $Index ,$BackupDirs.Count Write-Progress -Activity $Text $status -PercentComplete ($Items / $SumMB*100) if ($File.Attributes -ne "Directory") {$count++} } } $SumCount+=$Count $SumTotalMB="{0:N2}" -f ($Items / 1MB) + " MB of Files" Logging "INFO" "----------------------" Logging "INFO" "Copied $SumCount files with $SumTotalMB" Logging "INFO" "$ErrorCount Files could not be copied" } #Check if Backupdir needs to be cleaned and create Backupdir $Count=(Get-ChildItem $Destination | where {$_.Attributes -eq "Directory"}).count Logging "INFO" "Check if there are more than $Versions Directories in the Backupdir" if ($count -lt $Versions) { Create-Backupdir } else { Delete-Backupdir Create-Backupdir } #Check if all Dir are existing and do the Backup $CheckDir=Check-Dir if ($CheckDir -eq $false) { Logging "ERROR" "One of the Directory are not available, Script has stopped" } else { Make-Backup $Enddate=Get-Date #-format dd.MM.yyyy-HH:mm:ss $span = $EndDate - $StartDate $Minutes=$span.Minutes $Seconds=$Span.Seconds Logging "INFO" "Backupduration $Minutes Minutes and $Seconds Seconds" Logging "INFO" "----------------------" Logging "INFO" "----------------------" } $file = "$Backupdir\Log.txt" $message = New-Object System.Net.Mail.MailMessage $message.subject = $subject $message.body = $body $message.to.add($to) $message.from = $username $message.attachments.add($file) $smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort); $smtp.EnableSSL = $true $smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password); $smtp.send($message)
Результат выполнения скрипта:
PS D:\Backup> D:\Backup\VM_HHD_BackupScript.ps1 30.09.2019-09:42:20 - INFO: ---------------------- 30.09.2019-09:42:20 - INFO: Start the Script 30.09.2019-09:42:20 - INFO: Check if there are more than 2 Directories in the Backupdir 30.09.2019-09:42:20 - INFO: Create Backupdir D:\Backup\Backup-2019-09-30-18390\ 30.09.2019-09:42:20 - INFO: Move Log file to D:\Backup\Backup-2019-09-30-18390\ 30.09.2019-09:42:20 - INFO: Continue with Log File at D:\Backup\Backup-2019-09-30-18390\ 30.09.2019-09:42:20 - INFO: Check if BackupDir and Destination exists 30.09.2019-09:42:20 - INFO: Started the Backup 30.09.2019-09:42:20 - INFO: Count all files and create the Top Level Directories 30.09.2019-09:42:21 - INFO: There are 2 Files with 22 728,00 MB of Files to copy 30.09.2019-09:54:54 - INFO: ---------------------- 30.09.2019-09:54:54 - INFO: Copied 2 files with 22 728,00 MB of Files 30.09.2019-09:54:54 - INFO: 0 Files could not be copied 30.09.2019-09:54:54 - INFO: Backupduration 12 Minutes and 33 Seconds 30.09.2019-09:54:54 - INFO: ---------------------- 30.09.2019-09:54:54 - INFO: ---------------------- PS D:\Backup\Backup-2019-09-30-18390>
Эту же информацию получаем на почту, указанную в настройках скрипта admin@domain.ru.
Остаётся добавить задание в планировщик