There have been many people wanting a job chaning solution for Veeam Backup or a way of running a maximum number of concurrent jobs. Many reasons for wanting to do this (ours was that we have a WAN link and 2 jobs saturates it, 3 make it run badly)
For all of those out there that wanted it here is a powershell script that does exactly that.
It accepts 2 command line parameters, 1 for a batch of jobs to run, this supports wild cards so you can run the script with *daily* to run all backups with Daily in their name. The second parameter is the number of concurrent jobs that you want to have running e.g. 2. The script will find all the jobs that match, list them and then wait untill less than the maximum backups are running, it will then kick off the next backup and wait until another 'slot' becomes avaliable before starting another backup.
As the script checks with Veeam as to which backups are running you can run the script more than once at the same time and it will still keep the total number of backups running accross all scripts to less than the maximum.
To run the script from the command line use something like this:
powershell -command ".\Runjobs.ps1 *daily* 4"
If you need to put spaces in it then you need to get funky with the powershell command line like this:
powershell -command "& 'c:\program files\Veeam\Backup and FastSCP\Runjobs.ps1' '*six hourly' 2"
The contents of the script is below, it will need saving as a powershell script i.e. with a .ps1 extension. If you cannot run scripts in powershell (this is the default) you will need to open powershell and type Set-ExecutionPolicy Unrestricted
This is my first powershell script so any comments/improvements would be welcomed

Cheers
Richard
###############################################
If ($args.Count -ne 2 -or $args[0] -eq "" -or $args[1] -eq 0) {
Write-Host "Incorrect arguments, syntax: runjobs JobContains MaxJobs";
Write-Host "eg: runjobs *Daily* 2";
Exit;
}
add-pssnapin veeampssnapin;
$JobList=@();
$runningjobs=@();
$JobMatch = $args[0];
$Maxjobs = $args[1];
Write-Host "Looking for jobs that match" $JobMatch;
Get-VBRJob | where {$_.Name -like $JobMatch} | foreach {$JobList += $_.name};
Write-Host "Found" $joblist.count "jobs";
If ($joblist -eq $null -or $joblist.count -eq 0) {
Write-Host "No Jobs match that string... exiting";
Exit;
}
$joblist = $joblist | Sort-Object
Write-Host "Jobs to run...";
ForEach ($job in $JobList) {Write-Host " " $job;}
ForEach ($job in $JobList) {
Do {
$runningjobs=@();
Get-VBRJob | where {$_.Control -eq "Start"} | foreach {$RunningJobs += $_.name};
If ($runningjobs.count -ge $Maxjobs) {
Write-Host "Waiting to start '" $job "' as " $runningjobs "are still running";
Start-Sleep -s 60;
}
}
While ($runningjobs.count -ge $Maxjobs)
Write-Host "Starting " $job;
Start-Job -scriptblock {add-pssnapin veeampssnapin; Start-VBRJob $args[0]} -ArgumentList $job;
Write-Host "Waiting for veeam to start the job";
Start-Sleep -s 60;
}
#############################