0

我想使用 Veeam 的免费版本在 Windows Hyper-V 2016 服务器上备份我的虚拟机。该工具的免费版本不提供定期备份的工具,因此我一直在寻找一种将其 API 与任务调度程序结合使用的方法。

在寻找解决方案的过程中,我遇到了这篇文章,其中包含了我所需要的所有详细信息:

https://blog.mwpreston.net/2015/04/29/scheduling-veeam-backup-free-edition-backups/

Param(
  [Parameter(Mandatory=$true)][string]$VM,
  [Parameter(Mandatory=$true)][string]$Destination,
  [Parameter(Mandatory=$true)][ValidateSet(0,4,5,6,9)][int]$Compression,
  [bool]$DisableQuiesce=$true,
  [Parameter(Mandatory=$true)][ValidateSet("Never","Tonight","TomorrowNight","In3days","In1Week","In2Weeks","In1Month")][string]$Autodelete
)
#Load Veeam Toolkit
& "C:\Program Files\Veeam\Backup and Replication\Backup\Initialize-VeeamToolkit.ps1"
#Validate any parameters
$vmentity = Find-VBRViEntity -Name $VM 
if ($vmentity -eq $null)
{
  Write-Host "VM: $VM not found" -ForegroundColor "red"
  exit
}
if (-Not (Test-Path $Destination))
{
  Write-Host "Destination: $vmname not valid" -ForegroundColor "red"
  exit
}
if ($DisableQuiesce -eq $true)
{
    Start-VBRZip -Entity $vmentity -Folder $destination -Compression $Compression -AutoDelete $Autodelete -DisableQuiesce
}
else
{
    Start-VBRZip -Entity $vmentity -Folder $destination -Compression $Compression -AutoDelete $Autodelete
}

但是,此页面上的 sript 仅支持备份单个 VM。我可以创建许多这样的脚本,但是最好有一个循环通过 VM 的脚本。

我想这就像循环遍历所有 VM 一样简单,但由于我没有使用 powershell 脚本的经验,也没有使用 Veeam,我正在寻找一些帮助/帮助来修改脚本以备份所有 VM。该页面的评论中有一些关于此的讨论,但似乎该博客文章已经更新,因此它不直接适用。

例如这样的:

(get-vm -ComputerName YOURSERVERFQDN | foreach { $_.Name }) -join "`",`"" | Tee-Object -Variable VMNames | Out-Null

额外的好处是在失败时添加某种电子邮件通知,但这有点超出了这个问题的主题。

4

1 回答 1

0

复活一个老问题,但显然 Q 有很多观点,所以我想我应该分享我正在工作的脚本的最终版本。这是基于我在某处找到的原始脚本的不同版本,为我的目的而修改的。

它不是超级优雅,但它可以完成工作,如果失败,它会通过电子邮件发送一些方便的错误消息。

Param(
  [Parameter(Mandatory=$false)][string]$hostname = 'yourhostname',
  [Parameter(Mandatory=$false)][string]$BackupDestination = '\\yourdestination',
  [ValidateSet(0,4,5,6,9)][int]$CompressionLevel = 5,
  [bool]$DisableQuiesce=$false,
  [ValidateSet("Never","Tonight","TomorrowNight","In3days","In1Week","In2Weeks","In1Month")][string]$Autodelete = "Tonight",
  [bool]$EnableNotification=$true,
  [string]$SMTPServer = 'smpt.yourmailserver.com'
)

##################################################################
# Notification Settings
##################################################################

# Email FROM
$EmailFrom = "veeam@domain"

# Email TO
$EmailTo = "you@domain"

# Email subject
$EmailSubject = "Veeam backup failed!"

##################################################################
# Email formatting
##################################################################

$style = "<style>BODY{font-family: Arial; font-size: 10pt;}"
$style = $style + "TABLE{border: 1px solid black; border-collapse: collapse;}"
$style = $style + "TH{border: 1px solid black; background: #dddddd; padding: 5px; }"
$style = $style + "TD{border: 1px solid black; padding: 5px; }"
$style = $style + "</style>"

try{

    #Load Veeam Toolkit
    & "C:\Program Files\Veeam\Backup and Replication\Console\Initialize-VeeamToolkit.ps1"

    #Gather VM list dynamically
    #Different methods of getting the vmlist
    #$Script:VMList= (Get-VM -ComputerName $hostname -Credential $currentUser)
    $script:VMList =  Find-VBRHvEntity | Where-Object {$_.Type -eq 'Vm' -and $_.PowerState -eq "PoweredOn"}

    #Add the hostname to the path in case you use some generic path
    #$BackupDestinationWithHostName = Join-Path $BackupDestination $hostname

    #Get the NAS credentials. This may not be needed depending on your setup. I am using active directy, but still found this to be the least painful solution
    $NASCredentials = Get-VBRCredentials -Name "veeam@domain"

    #Perform backup task for each identified VM
    foreach ($vmentity in $VMList) {
        #Perform the actual backup
        $ZIPSession = Start-VBRZip -NetworkCredentials $NASCredentials -Entity $vmentity -Folder $BackupDestination -Compression $CompressionLevel -DisableQuiesce:($DisableQuiesce) -AutoDelete $Autodelete
        #$ZIPSession = Start-VBRZip -Entity $vmentity -Folder $BackupDestination -Compression $CompressionLevel -DisableQuiesce:($DisableQuiesce) -AutoDelete $Autodelete

        $TaskSessions = $ZIPSession.GetTaskSessions().logger.getlog().updatedrecords
        $FailedSessions = $TaskSessions | where {$_.status -eq "EWarning" -or $_.Status -eq "EFailed"}

        If ($EnableNotification) {
            if ($FailedSessions -ne $Null) {
                $sendFailedEmail = $true
                $thisMessage = ($ZIPSession | Select-Object @{n="Name";e={($_.name).Substring(0, $_.name.LastIndexOf("("))}} ,@{n="Start Time";e={$_.CreationTime}},@{n="End Time";e={$_.EndTime}},Result,@{n="Details";e={$FailedSessions.Title}})
                $MessageBody += $thisMessage
            }
        }
    }

    If (($EnableNotification -eq $true) -and ($sendFailedEmail -eq $true)) {
        $Message = New-Object System.Net.Mail.MailMessage $EmailFrom, $EmailTo
        $Message.Subject = $EmailSubject
        $Message.IsBodyHTML = $True
        $message.Body = $MessageBody | ConvertTo-Html -head $style | Out-String
        $SMTP = New-Object Net.Mail.SmtpClient($SMTPServer)
        $SMTP.Send($Message)
    }
} catch{
    $ErrorMessage = $_.Exception.Message
    $Message = New-Object System.Net.Mail.MailMessage $EmailFrom, $EmailTo
    $Message.Subject = "Unexpected error in Veeam powershell script"
    $Message.Body = $ErrorMessage
    $SMTP = New-Object Net.Mail.SmtpClient($SMTPServer)
    $SMTP.Send($Message)

    echo $_.Exception.Message
} finally { 
    # Any cleanup you need to perform. I am shutting down the server as it restarts on an automatic cycle when the task has to run again.
    Stop-Computer
}
于 2018-11-27T22:13:40.843 回答