Script is made to control Veeam VBR
Thanks for taking a look at my massive feature creep ;)
<#
.SYNOPSIS
Startet ein Veeam VBR Job
.DESCRIPTION
Startet einen VBR Job basierend auf den Namen.
Ursprünglicher Zweck war ein Verknüpfung von Jobs (z.B. als Pre-Execution Skript)
.PARAMETER JobName
Job-Name des Backup Jobs
.PARAMETER JobType
Typ des Backup Jobs
Erlaubte Typen: VAW, VAL, VMware,
Nicht erlaubte: Typen: HyperV, PVE
$Get-VBRBackup | Select-Object -Property Name,TypeToString,JobType
Backup Pretty Verbose Typ im Skript Notizen
########################################################################################################
Backup Copy Job Backup Copy SimpleBackupCopyPolicy / /
VAW Managed SRV Windows Agent Backup EpAgentBackup VAW CMDlet deprecated for Agent backups
VAW Managed PC Windows Agent Policy EpAgentPolicy VAW CMDlet deprecated for Agent backups
VAL Managed SRV Linux Agent Backup EpAgentBackup VAL CMDlet deprecated for Agent backups
VAL Managed PC Linux Agent Policy EpAgentPolicy VAL CMDlet (probably) deprecated for Agent backups # UNGETESTET WERTE!
Proxmox VE Proxmox Backup VmbApiPolicyTempJob PVE Nicht nutzbar mit Powershell via Start-VBRJob
VMware VMware Backup Backup Backup VMware
Hyper-V
.EXAMPLE
Start-VeeamJob.ps1 -JobName
passes F1234567-1abc-1234-ab1c-1a2345b6c78d to $JobName
.NOTES
Author : Appoxo
Version : 2.0
.LINK
Job-ID auslesen:
Get-VBRComputerBackupJob | Where-Object Name -CLike "*Name*" | Select-Object -Property Id, Name
#>
[CmdletBinding()]
Param(
[Parameter(Mandatory = $true,
HelpMessage = "Enter Job-Name of the VBR-Job")]
[String]
$JobName,
[Parameter(Mandatory = $true,
HelpMessage = "Art des VBR-Jobs. Die Bezichnung ist NICHT canse-sensitiv!")]
[string]
$JobType
)
Begin {
Write-Host "Script started successfully"
$ExitCode = 0
#TimeStamp Logging:
function Get-TimeStamp {return "{0:yy/MM/dd} {0:HH:mm:ss}" -f (Get-Date)}
<#
#Debug Values:
$JobName = "L1 Backup Appoxo-PC2 (Games)"
$JobType = "VAW"
#>
# Variablen
$workingDir = "C:\Skripte\SkriptLogs"
$log = "$($workingDir)\Log-StartVeeamJob.log"
$JobDetails = Get-VBRBackup | Where-Object Name -EQ "$($JobName)"
$timeout = 9
# Vorbereitung
if ($JobType -in @("VAW","VAL","VMware")){
Write-Host "Valid backup type selected"
$JobTypUnbestimmt = 0
}
else {
Write-Host "Invalid backup type selected. Please choose something else :)"
$ExitCode = 1
exit $ExitCode
}
if (Test-Path -Path $workingDir) {
} else {
New-Item -ItemType Directory -Path "$workingDir"
}
if (-not (Test-Path -Path $log -PathType Leaf)) {
New-Item -ItemType file -Path $log
Add-Content -Path $log "Log zur Überprüfung der Start von VBR-Jobs"
}
}
Process {
Write-Host "You passed the following information:"
$data = @([PSCustomObject]@{"Job Details"="$($JobDetails.Name)"; "Selected Job Type"="$($JobType)"})
$data | Format-Table -AutoSize
Write-Host "The following Job-ID was found for this job: $($JobDetails.JobId)"
Write-Host "If there is an error please abort NOW."
while ($timeout -gt 0) {
Write-Host -NoNewline "`rThe script starts in $($timeout)"
Start-Sleep -Seconds 1
$timeout--
}
Write-Host "Starting script now!"
Write-Output "$(Get-TimeStamp) Start des Backup Job Skripts. Für den Job '$($JobDetails.Name)' wurde die Job-ID $($JobDetails.JobId) gefunden!" | Add-Content -Path $log
try{
$startTime = Get-Date
Write-Host "Validating input... This may take a while"
if((($JobType -in @("VAW","VAL"))) -AND (($JobDetails.JobType -in @("EpAgentBackup","EpAgentPolicy")))) {
Write-Host "Valid backup type '$($JobDetails.TypeToString)' was found. Starting now!"
Start-VBRComputerBackupJob -Job $JobName | Select-Object -OutVariable JobResult
}
elseif (($JobType -in @("VMware")) -AND (($JobDetails.JobType -in @("Backup")))) {
Write-Host "Valid backup type '$($JobDetails.TypeToString)' was found. Starting now!"
Start-VBRJob -Job $JobName | Select-Object -OutVariable JobResult
}
elseif (($JobType -in @("PVE")) -AND (($JobDetails.JobType -in @("VmbApiPolicyTempJob")))) {
Write-Host "Der Job des Typs $JobType ist aktuell nicht implementiert"
$ExitCode = 1
exit $ExitCode
<#
Write-Host "Valid backup type '$($JobDetails.TypeToString)' was found. Starting now!"
Start-VBRJob -Job $JobName | Select-Object -OutVariable JobResult
#>
}
else {
Write-Host "Invalid backup type '$($JobDetails.TypeToString)' was found. Please restart the script!"
Write-Output "$(Get-TimeStamp) Bestimmung des Typs für den Job '$($JobDetails.Name)' nicht erfolgreich. Angegeben wurde '$($JobType)'" | Add-Content -Path $log
$ExitCode = 1
$JobTypUnbestimmt = 1
}
# Job Result report
if(($JobTypUnbestimmt -EQ 0) -AND ($JobResult.State -EQ "Stopped") -AND ($JobResult.Result -EQ "Success")){
Write-Host "Execution of the Job '$($JobName) was successful"
Write-Output "$(Get-TimeStamp) Backup Job $($JobDetails.Name) erfolgreich ausgeführt" | Add-Content -Path $log
$ExitCode = 0
} else{
Write-Host "Execution of the Job '$($JobName) encountered an error. Please check the VBR-Console"
Write-Output "$(Get-TimeStamp) Fehler beim ausführen vom Backup Job '$($JobDetails.Name)'" | Add-Content -Path $log
$ExitCode = 1
}
#Stats
$endTime = Get-Date
$executionTime = $endTime - $startTime
} catch {
Write-Host "Something went wrong during execution"
Write-Host $_ # This prints the actual error
Write-Output "$(Get-TimeStamp) Error: $($_)" | Add-Content -Path $log
$ExitCode = 1
}
}
End {
Write-Output "$(Get-TimeStamp) Skript abgeschlossen für $($JobDetails.Name) Job-ID $($JobDetails.Id)" | Add-Content -Path $log
Write-Host "Script ended."
$seconds = "{0:N2}" -f $executionTime.TotalSeconds
$minutes = "{0:N2}" -f ($executionTime.TotalSeconds / 60)
Write-Host "Time for stats! The script took $($seconds) seconds or $($minutes) minutes)"
exit $ExitCode
}
Just looking at it from the point of view of making the script more portable and easier for someone else to run, there are a few things I would address.
The first is the
Write-Host
commands all over the script. I would recommend converting those toWrite-Verbose
. Here is a great explanation when to useWrite-Host
vs other outputs.There are also numerous
Write-Output
commands in the script. Anything sent to theWrite-Output
will be returned to the calling console. If you need to take additional actions based on the results of this script, this could cause issues. You can run into problems with theNew-Item
commands in there too, as they will produce output. You might consider saving them to a variable or piping toOut-Null
.Also, there is no need to call exit and set an exit code in the way you are. If you want to write and error but have the script continue you can use,
Write-Error
. If you want the processing to terminate then usethrow
. Doing it this way will allow PowerShell’s built-in error handling to take care of the exit codes. It will also give you greater flexibility with using Error Action Preferences and using try/catch statements.Finally, you have a path hardcoded for the workingDir. I would suggest making this a parameter or using an environment variable as this will make it more portable. Also, when creating the log variable, you will want to use the Join-Path cmdlet instead of just joining strings.
Saved for reference. Most likely I won't improve this script as it was just a hobby experiment and has little value at work but I will definitely keep your advice in mind for future scripts with actual value.
And I believe I already have some scripts in mind. :)
Thank you very much for taking a look!