230 lines
7.9 KiB
PowerShell
230 lines
7.9 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Herstart relevante services wanneer een VSS back-up is mislukt.
|
|
|
|
.DESCRIPTION
|
|
- Zoekt in de Event Logs (Application/System) naar recente VSS-fouten.
|
|
- (Optioneel) Controleert VSS-writers via 'vssadmin list writers' op Failed.
|
|
- Herstart een configureerbare set van VSS-gerelateerde services.
|
|
- Logt acties naar bestand en uitvoer; verifieert na afloop de writer-status.
|
|
|
|
.PARAMETER LookbackMinutes
|
|
Periode (minuten) om terug te kijken voor VSS-fouten in Event Logs.
|
|
|
|
.PARAMETER RequireFailedWriter
|
|
Alleen services herstarten als er daadwerkelijk één of meer VSS-writers in Failed staan.
|
|
|
|
.PARAMETER Force
|
|
Stop-Service gebruikt -Force wanneer nodig.
|
|
|
|
.PARAMETER LogPath
|
|
Pad naar logbestand.
|
|
|
|
.PARAMETER ServiceList
|
|
Overschrijf de standaardlijst met te herstarten services (servicenamen, niet weergavenamen).
|
|
|
|
.NOTES
|
|
- Run als Administrator.
|
|
- Pas de standaard ServiceList aan voor de betreffende serverrol(len).
|
|
#>
|
|
|
|
[CmdletBinding()]
|
|
param(
|
|
[int]$LookbackMinutes = 60,
|
|
[switch]$RequireFailedWriter,
|
|
[switch]$Force,
|
|
[string]$LogPath = "C:\Windows\Temp\VSS-Restart-$(Get-Date -Format 'yyyyMMdd_HHmmss').log",
|
|
[string[]]$ServiceList = @(
|
|
# Kern VSS
|
|
'VSS', # Volume Shadow Copy
|
|
'SwPrv', # Microsoft Software Shadow Copy Provider
|
|
'EventSystem', # COM+ Event System
|
|
'COMSysApp', # COM+ System Application (soms niet nodig/aanwezig)
|
|
|
|
# Veelvoorkomende writers (pas aan op rol)
|
|
'SQLWriter', # SQL Server VSS Writer (indien aanwezig)
|
|
'IISADMIN', # IIS Admin Service (indien aanwezig)
|
|
'W3SVC', # World Wide Web Publishing (indien aanwezig)
|
|
'BITS', # Background Intelligent Transfer Service (soms storend bij backups)
|
|
'wbengine', # Windows Backup Engine (indien gebruikt)
|
|
|
|
# Hyper-V (host of guest; alleen herstarten als aanwezig)
|
|
'vmicvss', # Hyper-V Volume Shadow Copy Requestor (Guest service)
|
|
'vmms' # Hyper-V Virtual Machine Management (Host)
|
|
)
|
|
)
|
|
|
|
# ---------- Auto-defaults wanneer GEEN parameters zijn meegegeven ----------
|
|
$NoParams = ($PSBoundParameters.Count -eq 0)
|
|
if ($NoParams) {
|
|
try {
|
|
if (-not (Test-Path -LiteralPath 'C:\Temp')) {
|
|
New-Item -ItemType Directory -Path 'C:\Temp' -Force | Out-Null
|
|
}
|
|
} catch {}
|
|
$LogPath = "C:\Temp\VSS-Restart-$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
|
|
}
|
|
# Force-effectiviteit wordt later bepaald met $ForceEffective i.p.v. $Force direct te wijzigen
|
|
$ForceEffective = ($NoParams -or $Force.IsPresent)
|
|
|
|
# ---------- Helpers ----------
|
|
function Write-Log {
|
|
param([string]$Message)
|
|
$stamp = (Get-Date).ToString('yyyy-MM-dd HH:mm:ss')
|
|
$line = "[$stamp] $Message"
|
|
Write-Output $line
|
|
try { Add-Content -Path $LogPath -Value $line -Encoding UTF8 -ErrorAction Stop } catch {}
|
|
}
|
|
|
|
function Test-VssErrors {
|
|
param([int]$Minutes)
|
|
$since = (Get-Date).AddMinutes(-$Minutes)
|
|
|
|
$filters = @(
|
|
@{ LogName='Application'; ProviderName='VSS' },
|
|
@{ LogName='System'; ProviderName='VolSnap' }, # Volsnap driver errors
|
|
@{ LogName='Application'; ProviderName='Backup' }, # Sommige backupapps loggen onder 'Backup'
|
|
@{ LogName='Application'; ProviderName='Windows Server Backup' } # WSB
|
|
)
|
|
|
|
$events = foreach ($f in $filters) {
|
|
try {
|
|
Get-WinEvent -FilterHashtable @{
|
|
LogName = $f.LogName
|
|
ProviderName = $f.ProviderName
|
|
Level = 2 # Error
|
|
StartTime = $since
|
|
} -ErrorAction SilentlyContinue
|
|
} catch {}
|
|
}
|
|
|
|
$hasErrors = $false
|
|
if ($events) {
|
|
$hasErrors = $true
|
|
Write-Log "VSS/VOLSNAP/Backup fouten gevonden sinds ${since}:"
|
|
$events | Sort-Object TimeCreated -Descending | Select-Object -First 10 |
|
|
ForEach-Object {
|
|
Write-Log (" {0:u} {1} {2}: {3}" -f $_.TimeCreated, $_.ProviderName, $_.Id, ($_.Message -replace '\r?\n',' '))
|
|
}
|
|
} else {
|
|
Write-Log "Geen VSS-gerelateerde fouten gevonden sinds $since."
|
|
}
|
|
return $hasErrors
|
|
}
|
|
|
|
function Get-VssWriterStatus {
|
|
# Parse 'vssadmin list writers' op Failed writers
|
|
$failed = @()
|
|
$all = @()
|
|
|
|
$output = & vssadmin list writers 2>$null
|
|
if (-not $output) {
|
|
Write-Log "Kon 'vssadmin list writers' niet uitvoeren of geen output."
|
|
return ,@(),@()
|
|
}
|
|
|
|
$current = [ordered]@{ Writer=''; State=''; LastError='' }
|
|
foreach ($line in $output) {
|
|
if ($line -match "^\s*Writer name:\s+'(.+?)'") {
|
|
if ($current.Writer) { $all += [pscustomobject]$current }
|
|
$current = [ordered]@{ Writer=$matches[1]; State=''; LastError='' }
|
|
} elseif ($line -match '^\s*State:\s+\[(\d+)\]\s+(.+)$') {
|
|
$current.State = "$($matches[1]) $($matches[2])"
|
|
} elseif ($line -match '^\s*Last error:\s+(.+)$') {
|
|
$current.LastError = $matches[1]
|
|
}
|
|
}
|
|
if ($current.Writer) { $all += [pscustomobject]$current }
|
|
|
|
foreach ($w in $all) {
|
|
if ($w.State -match '^\s*9\b|Failed') {
|
|
$failed += $w
|
|
}
|
|
}
|
|
return ,$failed,$all
|
|
}
|
|
|
|
function Restart-ServiceSafe {
|
|
param(
|
|
[string]$Name,
|
|
[switch]$ForceStop
|
|
)
|
|
try {
|
|
$svc = Get-Service -Name $Name -ErrorAction Stop
|
|
} catch {
|
|
Write-Log "Service '$Name' niet gevonden; overslaan."
|
|
return
|
|
}
|
|
|
|
# Sommige services zijn al gestopt of disabled
|
|
if ($svc.Status -eq 'Running') {
|
|
Write-Log "Stoppen service '$Name'..."
|
|
try {
|
|
if ($ForceStop) {
|
|
Stop-Service -Name $Name -Force -ErrorAction Stop
|
|
} else {
|
|
Stop-Service -Name $Name -ErrorAction Stop
|
|
}
|
|
$svc.WaitForStatus('Stopped','00:00:20')
|
|
} catch {
|
|
Write-Log "Kon service '$Name' niet stoppen: $($_.Exception.Message)"
|
|
}
|
|
} else {
|
|
Write-Log "Service '$Name' is niet Running (status=$($svc.Status)); stop stap overslaan."
|
|
}
|
|
|
|
Write-Log "Starten service '$Name'..."
|
|
try {
|
|
Start-Service -Name $Name -ErrorAction Stop
|
|
(Get-Service -Name $Name).WaitForStatus('Running','00:00:20')
|
|
Write-Log "Service '$Name' draait."
|
|
} catch {
|
|
Write-Log "Kon service '$Name' niet starten: $($_.Exception.Message)"
|
|
}
|
|
}
|
|
|
|
# ---------- Main ----------
|
|
Write-Log "=== VSS Service Restart Script gestart op $(hostname) ==="
|
|
Write-Log "Logbestand: $LogPath"
|
|
|
|
$hasVssErrors = Test-VssErrors -Minutes $LookbackMinutes
|
|
|
|
$failedWriters = @()
|
|
$allWriters = @()
|
|
$failedWriters, $allWriters = Get-VssWriterStatus
|
|
|
|
if ($failedWriters.Count -gt 0) {
|
|
Write-Log "VSS-writers in FAILED staat:"
|
|
$failedWriters | ForEach-Object { Write-Log (" {0} | State={1} | LastError={2}" -f $_.Writer, $_.State, $_.LastError) }
|
|
} else {
|
|
Write-Log "Geen FAILED VSS-writers gedetecteerd."
|
|
}
|
|
|
|
$shouldAct = $hasVssErrors -or ($failedWriters.Count -gt 0)
|
|
if ($RequireFailedWriter -and $failedWriters.Count -eq 0) {
|
|
$shouldAct = $false
|
|
Write-Log "RequireFailedWriter is ingeschakeld en er zijn geen failed writers; geen services herstart."
|
|
}
|
|
|
|
if ($shouldAct) {
|
|
Write-Log "Services worden herstart. Aantal in lijst: $($ServiceList.Count)."
|
|
foreach ($svcName in $ServiceList) {
|
|
Restart-ServiceSafe -Name $svcName -ForceStop:$ForceEffective
|
|
}
|
|
|
|
Start-Sleep -Seconds 5
|
|
Write-Log "Hercontrole VSS-writers na herstart..."
|
|
$failedAfter, $allAfter = Get-VssWriterStatus
|
|
|
|
if ($failedAfter.Count -eq 0) {
|
|
Write-Log "Alle VSS-writers zijn nu OK."
|
|
exit 0
|
|
} else {
|
|
Write-Log "Nog steeds FAILED VSS-writers na herstart:"
|
|
$failedAfter | ForEach-Object { Write-Log (" {0} | State={1} | LastError={2}" -f $_.Writer, $_.State, $_.LastError) }
|
|
exit 2
|
|
}
|
|
} else {
|
|
Write-Log "Geen actie ondernomen; geen relevante fouten binnen de lookback of policy verhindert actie."
|
|
exit 0
|
|
} |