diff --git a/veeam.ps1 b/veeam.ps1 new file mode 100644 index 0000000..3e12ffb --- /dev/null +++ b/veeam.ps1 @@ -0,0 +1,115 @@ +# 引入 Veeam 的 PowerShell 模块 +Add-PSSnapin -Name VeeamPSSnapIn -ErrorAction SilentlyContinue + +# 配置 Pushgateway 的地址、Job名称和当前实例名 +$PushgatewayUrl = "http://10.150.117.190:9091" +$JobName = "veeam_backup" +$InstanceName = $env:COMPUTERNAME + +# 定义指标保存路径:当前目录下的 veeam_metrics.prom +$OutputFile = Join-Path -Path $PWD.Path -ChildPath "veeam_metrics.prom" + +# ================== Linux 上传配置 ================== +$linuxUser = "root" +$linuxIP = "10.150.117.190" +$linuxPath = "/opt/prom_textfile/" +$localFile = ".\veeam_metrics.prom" + +# ================== 无限循环:每分钟执行一次 ================== +while ($true) { + + $Metrics = @() + + # Prometheus 标准头部 + $Metrics += "# HELP veeam_job_status Veeam backup job status (0=Success,1=Warning,2=Failed,3=None)" + $Metrics += "# TYPE veeam_job_status gauge" + $Metrics += "# HELP veeam_job_is_running Veeam job is running (1=running,0=idle)" + $Metrics += "# TYPE veeam_job_is_running gauge" + $Metrics += "# HELP veeam_job_progress_percent Veeam job progress percentage" + $Metrics += "# TYPE veeam_job_progress_percent gauge" + $Metrics += "# HELP veeam_job_backup_size_gb Veeam backup size in GB" + $Metrics += "# TYPE veeam_job_backup_size_gb gauge" + $Metrics += "# HELP veeam_job_data_size_gb Veeam data size processed in GB" + $Metrics += "# TYPE veeam_job_data_size_gb gauge" + $Metrics += "# HELP veeam_job_duration_seconds Veeam job duration in seconds" + $Metrics += "# TYPE veeam_job_duration_seconds gauge" + $Metrics += "# HELP veeam_repo_free_space_gb Veeam repository free space in GB" + $Metrics += "# TYPE veeam_repo_free_space_gb gauge" + $Metrics += "# HELP veeam_repo_total_space_gb Veeam repository total space in GB" + $Metrics += "# TYPE veeam_repo_total_space_gb gauge" + $Metrics += "" + + # ================== 1. 抓取备份任务指标 ================== + $Jobs = Get-VBRJob | Where-Object { $_.JobType -eq "Backup" } + + foreach ($Job in $Jobs) { + $LastSession = $Job.FindLastSession() + $Status = if ($LastSession) { $LastSession.Result } else { "None" } + $State = if ($LastSession) { $LastSession.State } else { "Idle" } + + $StatusCode = switch ($Status) { + "Success" { 0 } + "Warning" { 1 } + "Failed" { 2 } + default { 3 } + } + + $IsRunning = if ($State -eq "Working") { 1 } else { 0 } + + $SafeJobName = $Job.Name -replace '[^a-zA-Z0-9_]', '_' + $CleanJobName = $SafeJobName -replace '[`"''\n\r]', '' + + $Metrics += "veeam_job_status{job=`"$JobName`", instance=`"$InstanceName`", job_name=`"$CleanJobName`"} $StatusCode" + $Metrics += "veeam_job_is_running{job=`"$JobName`", instance=`"$InstanceName`", job_name=`"$CleanJobName`"} $IsRunning" + + $Progress = if ($LastSession -and $State -eq "Working") { $LastSession.Progress.Percents } else { 0 } + $Metrics += "veeam_job_progress_percent{job=`"$JobName`", instance=`"$InstanceName`", job_name=`"$CleanJobName`"} $Progress" + + $BackupSizeGB = if ($LastSession) { [math]::Round($LastSession.Info.Progress.BackupSize / 1GB, 2) } else { 0 } + $Metrics += "veeam_job_backup_size_gb{job=`"$JobName`", instance=`"$InstanceName`", job_name=`"$CleanJobName`"} $BackupSizeGB" + + $DataSizeGB = if ($LastSession) { [math]::Round($LastSession.Info.Progress.DataSize / 1GB, 2) } else { 0 } + $Metrics += "veeam_job_data_size_gb{job=`"$JobName`", instance=`"$InstanceName`", job_name=`"$CleanJobName`"} $DataSizeGB" + + $DurationSeconds = if ($LastSession -and $LastSession.EndTime) { + ($LastSession.EndTime - $LastSession.CreationTime).TotalSeconds + } else { 0 } + $Metrics += "veeam_job_duration_seconds{job=`"$JobName`", instance=`"$InstanceName`", job_name=`"$CleanJobName`"} $DurationSeconds" + } + + # ================== 2. 抓取备份存储库空间指标 ================== + $Repositories = Get-VBRBackupRepository + foreach ($Repo in $Repositories) { + $Path = $Repo.Path + $DriveLetter = (Split-Path $Path -Qualifier).TrimEnd(':') + $DiskInfo = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='$DriveLetter`:'" -ErrorAction SilentlyContinue + + if ($DiskInfo) { + $FreeSpaceGB = [math]::Round($DiskInfo.FreeSpace / 1GB, 2) + $TotalSpaceGB = [math]::Round($DiskInfo.Size / 1GB, 2) + } else { + $FreeSpaceGB = 0 + $TotalSpaceGB = 0 + } + + $SafeRepoName = $Repo.Name -replace '[^a-zA-Z0-9_]', '_' + $CleanRepoName = $SafeRepoName -replace '[`"''\n\r]', '' + + $Metrics += "veeam_repo_free_space_gb{job=`"$JobName`", instance=`"$InstanceName`", repo_name=`"$CleanRepoName`"} $FreeSpaceGB" + $Metrics += "veeam_repo_total_space_gb{job=`"$JobName`", instance=`"$InstanceName`", repo_name=`"$CleanRepoName`"} $TotalSpaceGB" + } + + # ================== ✅ 最后加一行空行,满足 node_exporter 要求 ================== + $Metrics += "" + + # ================== 输出纯 Linux 格式 ================== + $MetricsBody = $Metrics -join "`n" + [System.IO.File]::WriteAllText($OutputFile, $MetricsBody, [System.Text.UTF8Encoding]::new($false)) + + # ================== 上传 Linux ================== + scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=NUL $localFile "${linuxUser}@${linuxIP}:${linuxPath}" + + Write-Host "`n✅ [$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss'))] 采集完成并上传 → 等待 60 秒后下一次`n" -ForegroundColor Green + + Start-Sleep -Seconds 60 +} \ No newline at end of file