<# .SYNOPSIS Acronis Universal Monitor — ОДИН скрипт для всех .DESCRIPTION Авто-обнаружение задач, отправка агрегированных данных в Zabbix. Работает с универсальным шаблоном на всех клиентах. #> # ==================== ЗАГРУЗКА КОНФИГА ==================== $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path $ConfigFile = Join-Path $ScriptDir "config.json" if (-not (Test-Path $ConfigFile)) { Write-Error "Конфиг не найден: $ConfigFile" exit 1 } $Config = Get-Content $ConfigFile -Raw -Encoding UTF8 | ConvertFrom-Json $Z_SENDER = $Config.zabbix_sender $Z_SERVER = $Config.zabbix_server $Z_HOST = $Config.zabbix_host $Z_TLS_ID = $Config.psk_identity $Z_TLS_KEY = $Config.psk_key_file $LOG_PATH = $Config.acronis_log_path $SCAN_DAYS = $Config.scan_days $MAX_AGE = $Config.max_age_seconds # =========================================================== function Send-ToZabbix { param([string]$Key, [int]$Value) $params = @( '-z', $Z_SERVER, '-s', $Z_HOST, '-k', $Key, '-o', $Value.ToString(), '--tls-connect', 'psk', '--tls-psk-identity', $Z_TLS_ID, '--tls-psk-file', $Z_TLS_KEY ) $result = & $Z_SENDER @params 2>&1 return -not ($result -match 'failed: [1-9]') } function Parse-AcronisTime { param([string]$Line) if ($Line -match '^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}):(\d{3})([\+\-]\d{2}:\d{2})') { $isoString = "$($matches[1]).$($matches[2])$($matches[3])" try { return [datetime]::Parse($isoString) } catch { return $null } } return $null } function Get-AllTaskUUIDs { param([string]$LogPath, [int]$Days) $dateLimit = (Get-Date).AddDays(-$Days) $uuids = @{} Get-ChildItem -Path $LogPath -Filter "*.log" -File | Where-Object { $_.LastWriteTime -gt $dateLimit } | ForEach-Object { if ($_.Name -match 'ti_demon_([0-9A-F-]{36})_') { $uuids[$matches[1].ToUpper()] = $true } } return $uuids.Keys } function Get-TaskStatus { param([string]$LogPath, [string]$TaskUUID) $logFile = Get-ChildItem -Path $LogPath -Filter "*$TaskUUID*.log" -File | Sort-Object LastWriteTime -Descending | Select-Object -First 1 if (-not $logFile) { return @{ Status = 1; Age = $MAX_AGE; Time = $null } } try { $content = Get-Content -Path $logFile.FullName -Raw -Encoding UTF8 $successLine = $content | Select-String 'Операция завершена успешно' | Select-Object -First 1 if ($successLine) { $time = Parse-AcronisTime -Line $successLine.Line $age = if ($time) { [math]::Round(((Get-Date) - $time).TotalSeconds) } else { $MAX_AGE } if ($age -lt 0) { $age = 0 } return @{ Status = 0; Age = $age; Time = $time } } else { return @{ Status = 1; Age = $MAX_AGE; Time = $null } } } catch { return @{ Status = 1; Age = $MAX_AGE; Time = $null } } } # ==================== ОСНОВНАЯ ЛОГИКА ==================== Write-Host "╔════════════════════════════════════════════╗" -ForegroundColor Cyan Write-Host "║ Acronis Monitor — Universal ║" -ForegroundColor Cyan Write-Host "╚════════════════════════════════════════════╝" -ForegroundColor Cyan Write-Host "Server: $Z_SERVER | Host: $Z_HOST | $(Get-Date)" Write-Host "" if (-not (Test-Path $LOG_PATH)) { Write-Error "Путь к логам не найден: $LOG_PATH" Send-ToZabbix -Key "acronis.status[all]" -Value 1 Send-ToZabbix -Key "acronis.age[oldest]" -Value $MAX_AGE exit 1 } $taskUUIDs = Get-AllTaskUUIDs -LogPath $LOG_PATH -Days $SCAN_DAYS if ($taskUUIDs.Count -eq 0) { Write-Warning "Задачи не найдены за $SCAN_DAYS дней!" Send-ToZabbix -Key "acronis.status[all]" -Value 1 Send-ToZabbix -Key "acronis.age[oldest]" -Value $MAX_AGE exit 1 } Write-Host "✅ Задач обнаружено: $($taskUUIDs.Count)" Write-Host "" $oldestAge = 0 $overallStatus = 0 foreach ($uuid in $taskUUIDs) { $task = Get-TaskStatus -LogPath $LOG_PATH -TaskUUID $uuid Write-Host " $(if($task.Status -eq 0){'✓'}else{'✗'}) ($([math]::Round($task.Age/3600,1))ч)" -ForegroundColor $(if($task.Status -eq 0){'Green'}else{'Red'}) if ($task.Status -ne 0) { $overallStatus = 1 } if ($task.Age -gt $oldestAge) { $oldestAge = $task.Age } } Write-Host "" Write-Host "📤 Отправка в Zabbix..." -ForegroundColor Cyan $statusSent = Send-ToZabbix -Key "acronis.status[all]" -Value $overallStatus $ageSent = Send-ToZabbix -Key "acronis.age[oldest]" -Value $oldestAge Write-Host " acronis.status[all] = $overallStatus $(if($statusSent){'✓'}else{'✗'})" -ForegroundColor $(if($overallStatus -eq 0){'Green'}else{'Red'}) Write-Host " acronis.age[oldest] = $oldestAge сек ($([math]::Round($oldestAge/3600,2)) ч) $(if($ageSent){'✓'}else{'✗'})" -ForegroundColor Gray if ($statusSent -and $ageSent) { Write-Host "✅ Все данные отправлены" -ForegroundColor Green } else { Write-Host "⚠️ Ошибка отправки" -ForegroundColor Yellow exit 1 }