Skip to main content
Solved

I am looking for Veeam powershell script to list jobname, server, status and last run for last 24 hours . this should include backup and copy jobs.


I am looking for Veeam powershell script to list jobname, server, status and last run for last 24 hours . this should include backup and copy jobs.

 

Kindly assist.

Best answer by Chris.Childerhose

@Bennet - this should fix it now and display on screen, plus export to CSV.

Import-Module Veeam.Backup.PowerShell -WarningAction SilentlyContinue

$results = @()

# Get backup copy jobs once
$backupCopyJobs = Get-VBRBackupCopyJob
$copyJobIds = $backupCopyJobs.Id

# Backup jobs only (exclude backup copy jobs)
foreach ($job in Get-VBRJob | Where-Object { $_.Id -notin $copyJobIds }) {
$lastSess = Get-VBRSession -Job $job |
Sort-Object CreationTime -Descending |
Select-Object -First 1

if (-not $lastSess) {
$results += [PSCustomObject]@{
'Job Name' = $job.Name
'Job Type' = 'Backup Job'
'Protected server name' = 'Job has not run yet'
'Status' = 'N/A'
'Last Run' = $null
}
continue
}

$fullSess = Get-VBRBackupSession -Id $lastSess.Id

foreach ($t in Get-VBRTaskSession -Session $fullSess) {
$results += [PSCustomObject]@{
'Job Name' = $job.Name
'Job Type' = 'Backup Job'
'Protected server name' = $t.Name
'Status' = $t.Status
'Last Run' = $t.Progress.StartTimeUtc.ToString('M/d/yyyy h:mm:ss tt') + ' UTC'
}
}
}

# Backup copy jobs
$allJobs = Get-VBRJob
$allBackupSessions = Get-VBRBackupSession

foreach ($copyJob in $backupCopyJobs) {
$convJob = $allJobs | Where-Object { $_.Id -eq $copyJob.Id }

if (-not $convJob) {
$results += [PSCustomObject]@{
'Job Name' = $copyJob.Name
'Job Type' = 'Backup Copy Job'
'Protected server name' = 'Unable to map copy job'
'Status' = 'Unknown'
'Last Run' = $null
}
continue
}

$workerJobs = $convJob.GetWorkerJobs()
$copySessions = @()

foreach ($worker in $workerJobs) {
$copySessions += $allBackupSessions | Where-Object { $_.JobId -eq $worker.Id }
}

$lastSess = $copySessions |
Sort-Object CreationTime -Descending |
Select-Object -First 1

if (-not $lastSess) {
$results += [PSCustomObject]@{
'Job Name' = $copyJob.Name
'Job Type' = 'Backup Copy Job'
'Protected server name' = 'Job has not run yet'
'Status' = 'N/A'
'Last Run' = $null
}
continue
}

foreach ($t in Get-VBRTaskSession -Session $lastSess) {
$results += [PSCustomObject]@{
'Job Name' = $copyJob.Name
'Job Type' = 'Backup Copy Job'
'Protected server name' = $t.Name
'Status' = $t.Status
'Last Run' = $t.Progress.StartTimeUtc.ToString('M/d/yyyy h:mm:ss tt') + ' UTC'
}
}
}

$results = $results | Sort-Object 'Job Type', 'Job Name', 'Protected server name'

# Show on screen
$results | Format-Table 'Job Name', 'Job Type', 'Protected server name', 'Status', 'Last Run' -AutoSize

# Export CSV
$csvPath = "E:\Software\Reports\VeeamJobDetails-Servers.csv"
$results | Export-Csv -Path $csvPath -NoTypeInformation -Encoding UTF8

Write-Host "CSV exported to $csvPath"

 

 

 
 
 

17 comments

Chris.Childerhose
Forum|alt.badge.img+21

Which version of Veeam are you using, as the commands could be slightly different, and you need to use PowerShell 7 for v13?

Here is some code to do this, but might need tweaking -

# Load Veeam PowerShell snap-in if needed
Add-PSSnapin VeeamPSSnapIn -ErrorAction SilentlyContinue

$since = (Get-Date).AddHours(-24)

# Get backup and backup copy job sessions from the last 24 hours
$sessions = Get-VBRBackupSession |
Where-Object {
$_.CreationTime -ge $since -and
($_.JobType -eq "Backup" -or $_.JobType -eq "BackupCopy")
}

$report = foreach ($s in $sessions) {
$job = Get-VBRJob | Where-Object { $_.Id.Guid -eq $s.JobId } | Select-Object -First 1

[pscustomobject]@{
JobName = $s.JobName
Server = if ($job) { $env:COMPUTERNAME } else { $null }
Status = $s.Result
LastRun = $s.EndTime
}
}

$report | Sort-Object JobName, LastRun -Descending | Format-Table -AutoSize
# Optional export:
# $report | Export-Csv "C:\Temp\Veeam_24h_Report.csv" -NoTypeInformation
 
 
 
 

Chris.Childerhose
Forum|alt.badge.img+21

Here is one that lists on screen and formats the output -

Add-PSSnapin VeeamPSSnapIn -ErrorAction SilentlyContinue

$since = (Get-Date).AddHours(-24)

$report = Get-VBRBackupSession |
Where-Object {
$_.CreationTime -ge $since -and
($_.JobType -eq "Backup" -or $_.JobType -eq "BackupCopy")
} |
Sort-Object JobName, EndTime -Descending |
Group-Object JobName |
ForEach-Object {
$latest = $_.Group | Sort-Object EndTime -Descending | Select-Object -First 1
[pscustomobject]@{
JobName = $latest.JobName
Server = $env:COMPUTERNAME
Status = $latest.Result
LastRun = $latest.EndTime
}
}

$report | Format-Table -AutoSize
 
 
 

  • Author
  • April 8, 2026

Would like to test in v12 and then later in V13. Can I get the server name as well associated with respective job name for last 24 hours along with status and last run details.


eblack
Forum|alt.badge.img+2
  • Influencer
  • April 8, 2026

Would like to test in v12 and then later in V13. Can I get the server name as well associated with respective job name for last 24 hours along with status and last run details.

I’ve had to adapt the majority of my v12 to v13 scripts. 


Chris.Childerhose
Forum|alt.badge.img+21

Yes, you can get the server name with status/run details -

##This is the server details script

Add-PSSnapin VeeamPSSnapIn -ErrorAction SilentlyContinue

$since = (Get-Date).AddHours(-24)

$report = Get-VBRBackupSession |
Where-Object { $_.CreationTime -ge $since } |
ForEach-Object {
$job = Get-VBRJob | Where-Object { $_.Id -eq $_.JobId } | Select-Object -First 1

[pscustomobject]@{
JobName = $_.JobName
Server = if ($job) { $job.Name } else { $null }
Status = $_.Result
LastRun = $_.EndTime
}
} |
Sort-Object JobName, LastRun -Descending

$report | Format-Table -AutoSize

# Optional:
# $report | Export-Csv "C:\Temp\Veeam_Last24Hours_Report.csv" -NoTypeInformation


##If you want only the latest session per job in the last 24 hours, use this version:

Add-PSSnapin VeeamPSSnapIn -ErrorAction SilentlyContinue

$since = (Get-Date).AddHours(-24)

$report = Get-VBRBackupSession |
Where-Object { $_.CreationTime -ge $since } |
Group-Object JobName |
ForEach-Object {
$latest = $_.Group | Sort-Object EndTime -Descending | Select-Object -First 1
$job = Get-VBRJob | Where-Object { $_.Id -eq $latest.JobId } | Select-Object -First 1

[pscustomobject]@{
JobName = $latest.JobName
Server = if ($job) { $job.Name } else { $null }
Status = $latest.Result
LastRun = $latest.EndTime
}
}

$report | Format-Table -AutoSize

 


Forum|alt.badge.img+3
  • Experienced User
  • April 8, 2026

Would like to test in v12 and then later in V13. Can I get the server name as well associated with respective job name for last 24 hours along with status and last run details.

Hi I would propose different strategies than what has been provided, but please clarify; by Server Name, you mean you want to know the status of the Backup Server (Veeam) itself or of the servers being protected? Perhaps you can do a mock-up in text quick, but usually for something like this you could use a script similar to this:

 

Import-Module Veeam.Backup.PowerShell -WarningAction SilentlyContinue #PowerShell doesn't like some of our cmdlet names and will print a warning about it; -WarningAction flag mutes this
$allJob = Get-VBRJob
$mostRecentSess = @()
Foreach($j in $allJob){
$lastSess = Get-VBRSession -Job $j | Sort-Object CreationTime -Descending | Select -First 1 #Get most recent session
If(-not ($lastSess)){
$data = "Job $($j.name) has not run yet"
$mostRecentSess += $data
Remove-Variable data
Continue
}
$fullSess = Get-VBRBackupSession -Id $lastSess.Id
$taskSess = Get-VBRTaskSession -Session $fullSess
Foreach($t in $taskSess){
$serverName = $t.name
$jobName = $j.Name
$result = $t.Status
$lastRun = $t.Progress.StartTimeUtc
$data = [PSCustomObject]@{
ServerName = $serverName
JobName = $jobName
Result = $result
LastBackupStartTimeUTC = $lastRun
}
$mostRecentSess += $data
Remove-Variable data
}
}

Here’s an example output from my lab:

 

PS /root> $mostRecentSess

ServerName            JobName                              Result LastBackupStartTimeUTC
----------            -------                              ------ ----------------------
HK-AlmaLinux-01       VMW-HK-ZFS                          Success 4/8/2026 6:36:23 AM
dd-tinyvm_replica     VMW-DD-KMS-server-test              Success 4/7/2026 3:40:16 PM
dd-tinyvm_restored    VMW-DD-KMS-server-test              Success 4/7/2026 3:40:16 PM
Job VMW-FK-RJ-Nano has not run yet

Is that mostly what you’re looking for?
 

Would like to test in v12 and then later in V13. Can I get the server name as well associated with respective job name for last 24 hours along with status and last run details.

I’ve had to adapt the majority of my v12 to v13 scripts. 

Curious, what did you need to “adapt”? For Veeam cmdlets, we intend that all supported cmdlets from our side worked from v12 to v13; PowerShell itself changed how some items are handled between PoSh 5 and PoSh 7, but that’s expected. But for Veeam cmdlets everything ought have worked seamlessly between versions (excepting cmdlets that had changes in our changelog naturally)


eblack
Forum|alt.badge.img+2
  • Influencer
  • April 8, 2026

Would like to test in v12 and then later in V13. Can I get the server name as well associated with respective job name for last 24 hours along with status and last run details.

Hi I would propose different strategies than what has been provided, but please clarify; by Server Name, you mean you want to know the status of the Backup Server (Veeam) itself or of the servers being protected? Perhaps you can do a mock-up in text quick, but usually for something like this you could use a script similar to this:

 

Import-Module Veeam.Backup.PowerShell -WarningAction SilentlyContinue #PowerShell doesn't like some of our cmdlet names and will print a warning about it; -WarningAction flag mutes this
$allJob = Get-VBRJob
$mostRecentSess = @()
Foreach($j in $allJob){
$lastSess = Get-VBRSession -Job $j | Sort-Object CreationTime -Descending | Select -First 1 #Get most recent session
If(-not ($lastSess)){
$data = "Job $($j.name) has not run yet"
$mostRecentSess += $data
Remove-Variable data
Continue
}
$fullSess = Get-VBRBackupSession -Id $lastSess.Id
$taskSess = Get-VBRTaskSession -Session $fullSess
Foreach($t in $taskSess){
$serverName = $t.name
$jobName = $j.Name
$result = $t.Status
$lastRun = $t.Progress.StartTimeUtc
$data = [PSCustomObject]@{
ServerName = $serverName
JobName = $jobName
Result = $result
LastBackupStartTimeUTC = $lastRun
}
$mostRecentSess += $data
Remove-Variable data
}
}

Here’s an example output from my lab:

 

PS /root> $mostRecentSess

ServerName            JobName                              Result LastBackupStartTimeUTC
----------            -------                              ------ ----------------------
HK-AlmaLinux-01       VMW-HK-ZFS                          Success 4/8/2026 6:36:23 AM
dd-tinyvm_replica     VMW-DD-KMS-server-test              Success 4/7/2026 3:40:16 PM
dd-tinyvm_restored    VMW-DD-KMS-server-test              Success 4/7/2026 3:40:16 PM
Job VMW-FK-RJ-Nano has not run yet

Is that mostly what you’re looking for?
 

Would like to test in v12 and then later in V13. Can I get the server name as well associated with respective job name for last 24 hours along with status and last run details.

I’ve had to adapt the majority of my v12 to v13 scripts. 

Curious, what did you need to “adapt”? For Veeam cmdlets, we intend that all supported cmdlets from our side worked from v12 to v13; PowerShell itself changed how some items are handled between PoSh 5 and PoSh 7, but that’s expected. But for Veeam cmdlets everything ought have worked seamlessly between versions (excepting cmdlets that had changes in our changelog naturally)

Most of it was rolling 5.1 to 7 in prod around the same time as v13. Some of the obj storage sync cmds we used dropped out if I recall also. 


  • Author
  • April 8, 2026

I am looking for protected server under each backup job / copy job name :

 

For eg:

Job Name   Protected server name      Status       Last Run

Backup Job_1        Server_A               Success     4/8/2026 6:20:00 AM UTC

Copy Job_1           Server_B               Success      4/8/2026 6:40:00 AM UTC


Chris.Childerhose
Forum|alt.badge.img+21

@Bennet - try this one as it uses the one David posted but tweaked to your output requirements.

Import-Module Veeam.Backup.PowerShell -WarningAction SilentlyContinue

$allJob = Get-VBRJob
$mostRecentSess = foreach($j in $allJob){
$lastSess = Get-VBRSession -Job $j | Sort-Object CreationTime -Descending | Select-Object -First 1

if(-not $lastSess){
[PSCustomObject]@{
'Job Name' = $j.Name
'Protected server name' = 'Job has not run yet'
'Status' = 'N/A'
'Last Run' = $null
}
continue
}

$fullSess = Get-VBRBackupSession -Id $lastSess.Id
$taskSess = Get-VBRTaskSession -Session $fullSess

foreach($t in $taskSess){
[PSCustomObject]@{
'Job Name' = $j.Name
'Protected server name' = $t.Name
'Status' = $t.Status
'Last Run' = $t.Progress.StartTimeUtc
}
}
}

$mostRecentSess |
Sort-Object 'Job Name','Protected server name' |
Format-Table 'Job Name','Protected server name','Status',
@{Name='Last Run'; Expression={ $_.'Last Run' }; FormatString='g'} -AutoSize

 


  • Author
  • April 8, 2026

Thank you for this, took some time to execute but when Ctrl+C was given it listed the output for backup jobs alone in desired format. Could you please confirm if this would fetch even the copy jobs as well ?


Chris.Childerhose
Forum|alt.badge.img+21

Thank you for this, took some time to execute but when Ctrl+C was given it listed the output for backup jobs alone in desired format. Could you please confirm if this would fetch even the copy jobs as well ?

It will not on Backup Copy jobs as you need to use the Get-VBRBackupCopyJob cmdlet for those.

 
 
 

  • Author
  • April 8, 2026

Can we tweak the script and have the report run for copy job as well ?


Chris.Childerhose
Forum|alt.badge.img+21

Can we tweak the script and have the report run for copy job as well ?

Yes, I just did this and added a column to specify what type of job it is reporting.  See below and depending on number of jobs this can take a bit a time to run.

Import-Module Veeam.Backup.PowerShell -WarningAction SilentlyContinue

$report = foreach ($job in (Get-VBRJob)) {
$lastSess = Get-VBRSession -Job $job |
Sort-Object CreationTime -Descending |
Select-Object -First 1

if (-not $lastSess) {
[PSCustomObject]@{
'Job Name' = $job.Name
'Job Type' = 'Backup Job'
'Protected server name' = 'Job has not run yet'
'Status' = 'N/A'
'Last Run' = $null
}
continue
}

$fullSess = Get-VBRBackupSession -Id $lastSess.Id
foreach ($t in (Get-VBRTaskSession -Session $fullSess)) {
[PSCustomObject]@{
'Job Name' = $job.Name
'Job Type' = 'Backup Job'
'Protected server name' = $t.Name
'Status' = $t.Status
'Last Run' = $t.Progress.StartTimeUtc.ToString('M/d/yyyy h:mm:ss tt') + ' UTC'
}
}
}

$report += foreach ($job in (Get-VBRBackupCopyJob)) {
$lastSess = Get-VBRBackupSession |
Where-Object { $_.JobId -eq $job.Id } |
Sort-Object CreationTime -Descending |
Select-Object -First 1

if (-not $lastSess) {
[PSCustomObject]@{
'Job Name' = $job.Name
'Job Type' = 'Backup Copy Job'
'Protected server name' = 'Job has not run yet'
'Status' = 'N/A'
'Last Run' = $null
}
continue
}

foreach ($t in (Get-VBRTaskSession -Session $lastSess)) {
[PSCustomObject]@{
'Job Name' = $job.Name
'Job Type' = 'Backup Copy Job'
'Protected server name' = $t.Name
'Status' = $t.Status
'Last Run' = $t.Progress.StartTimeUtc.ToString('M/d/yyyy h:mm:ss tt') + ' UTC'
}
}
}

$report |
Sort-Object 'Job Type', 'Job Name', 'Protected server name' |
Format-Table 'Job Name', 'Job Type', 'Protected server name', 'Status', 'Last Run' -AutoSize
 
 
 

  • Author
  • April 8, 2026

Thank you. The copy jobs are completed in console but they are showing as Job has not run yet in the script output. The copy job is set to run immediately after the backup job, also would be helpful to have the output to be exported to .csv file.

 

 


Chris.Childerhose
Forum|alt.badge.img+21
  • Veeam Legend, Veeam Vanguard
  • Answer
  • April 8, 2026

@Bennet - this should fix it now and display on screen, plus export to CSV.

Import-Module Veeam.Backup.PowerShell -WarningAction SilentlyContinue

$results = @()

# Get backup copy jobs once
$backupCopyJobs = Get-VBRBackupCopyJob
$copyJobIds = $backupCopyJobs.Id

# Backup jobs only (exclude backup copy jobs)
foreach ($job in Get-VBRJob | Where-Object { $_.Id -notin $copyJobIds }) {
$lastSess = Get-VBRSession -Job $job |
Sort-Object CreationTime -Descending |
Select-Object -First 1

if (-not $lastSess) {
$results += [PSCustomObject]@{
'Job Name' = $job.Name
'Job Type' = 'Backup Job'
'Protected server name' = 'Job has not run yet'
'Status' = 'N/A'
'Last Run' = $null
}
continue
}

$fullSess = Get-VBRBackupSession -Id $lastSess.Id

foreach ($t in Get-VBRTaskSession -Session $fullSess) {
$results += [PSCustomObject]@{
'Job Name' = $job.Name
'Job Type' = 'Backup Job'
'Protected server name' = $t.Name
'Status' = $t.Status
'Last Run' = $t.Progress.StartTimeUtc.ToString('M/d/yyyy h:mm:ss tt') + ' UTC'
}
}
}

# Backup copy jobs
$allJobs = Get-VBRJob
$allBackupSessions = Get-VBRBackupSession

foreach ($copyJob in $backupCopyJobs) {
$convJob = $allJobs | Where-Object { $_.Id -eq $copyJob.Id }

if (-not $convJob) {
$results += [PSCustomObject]@{
'Job Name' = $copyJob.Name
'Job Type' = 'Backup Copy Job'
'Protected server name' = 'Unable to map copy job'
'Status' = 'Unknown'
'Last Run' = $null
}
continue
}

$workerJobs = $convJob.GetWorkerJobs()
$copySessions = @()

foreach ($worker in $workerJobs) {
$copySessions += $allBackupSessions | Where-Object { $_.JobId -eq $worker.Id }
}

$lastSess = $copySessions |
Sort-Object CreationTime -Descending |
Select-Object -First 1

if (-not $lastSess) {
$results += [PSCustomObject]@{
'Job Name' = $copyJob.Name
'Job Type' = 'Backup Copy Job'
'Protected server name' = 'Job has not run yet'
'Status' = 'N/A'
'Last Run' = $null
}
continue
}

foreach ($t in Get-VBRTaskSession -Session $lastSess) {
$results += [PSCustomObject]@{
'Job Name' = $copyJob.Name
'Job Type' = 'Backup Copy Job'
'Protected server name' = $t.Name
'Status' = $t.Status
'Last Run' = $t.Progress.StartTimeUtc.ToString('M/d/yyyy h:mm:ss tt') + ' UTC'
}
}
}

$results = $results | Sort-Object 'Job Type', 'Job Name', 'Protected server name'

# Show on screen
$results | Format-Table 'Job Name', 'Job Type', 'Protected server name', 'Status', 'Last Run' -AutoSize

# Export CSV
$csvPath = "E:\Software\Reports\VeeamJobDetails-Servers.csv"
$results | Export-Csv -Path $csvPath -NoTypeInformation -Encoding UTF8

Write-Host "CSV exported to $csvPath"

 

 

 
 
 

  • Author
  • April 9, 2026

Thanks a lot, this worked and I now have the desired report. One more query is there a way to capture the failure message for protected server backup failure in the report via script ?


Chris.Childerhose
Forum|alt.badge.img+21

I can check and see on that.  I will get back.