powershell:ad:healthcheck
Inhaltsverzeichnis
ad-healthcheck.ps1
Das Skript automatisiert den regelmäßig erforderlichen AD-Healthcheck
Am längsten dauert die Abfrage der Eventlogs, wenn diese nicht zu groß werden, beschleunigt sich die Ausführung erheblich.
Der Replikationstest funktionert nur von einem Rechner mit Windows 8 mit RSAT-Tools(?) Zumindest gibt es diesen Befehl in der Powershell unter Windows 2008R2 nicht ausführen.
Skript
ad-healthcheck.ps1
Das Skript automatisiert den regelmäßig erforderlichen AD-Healthcheck
Am längsten dauert die Abfrage der Eventlogs, wenn diese nicht zu groß werden, beschleunigt sich die Ausführung erheblich.
Der Replikationstest funktionert nur von einem Rechner mit Windows 8 mit RSAT-Tools(?) Zumindest gibt es diesen Befehl in der Powershell unter Windows 2008R2 nicht ausführen.
Skript
- ad-healthcheck.ps1
<#AD-Healthcheck Autor: Henning Löser version: 1.0 Was macht das Skript? Abfolge der Befehlszeilen für den AD-Healthcheck. ACHTUNG: Wird das Skript aus der ISE ausgeführt, so kann keine Logdatei erstellt und geöffnet werden! #> $SmtpServer=EIGENER-EMAIL-SERVER $SmtpSender=EIGENE-ABSENDER-EMAIL $SmtpRecipient=EIGENE-EMPFÄNGER-EMAIL $LocalSystem = (Get-WmiObject -Class Win32_ComputerSystem).name $timestamp=(Get-Date -Format yyyMMdd-Hmmss) $LogPath="C:\ProgramData\Skripte\logs\ad-healthcheck" $LogFile="$logpath\$timestamp`.$localsystem`.ad-healtcheck.txt" " " | Out-File -Encoding utf8 -filepath $logfile -Append $start=Get-Date -Format "dddd, dd.MM.yyy H:mm:ss" "Domaincheck gestartet: "+$start | Out-File -Encoding utf8 -filepath $logfile -Append "---------- " | Out-File -Encoding utf8 -filepath $logfile -Append " " | Out-File -Encoding utf8 -filepath $logfile -Append # Skript nur unter einem Domänen-Admin-Account ausführen if (Get-ADGroupMember "Domänen-Admins" | Where-Object {$_.SamAccountName -eq $env:Username }) { "Das Skript wird unter dem Account von `""+$env:Username+"`" ausgeführt." | Out-File -Encoding utf8 -filepath $logfile -Append } else { "Das Skript kann nicht unter dem Account von `""+$env:Username+"`" ausgeführt werden, da es kein Domänen-Admin-Account ist!" | Out-File -Encoding utf8 -filepath $logfile -Append Send-MailMessage -SmtpServer "$SmtpServer" -from "$SmtpSender" -to "$SmtpRecipient" -Subject "AD-Healthcheck vom $start`: Prüfung nicht möglich" -body "Das Skript funktioniert nur unter einem Domänen-Admin-Account. `nDer Benutzer `"$env:Username`" erfüllt diese Bedingung nicht." -Encoding utf8 break #Script wird beendet } ##### # Alle aktuellen Domänencontroller finden: ## $domain_dcs = Get-ADDomainController -Filter * | Select-Object hostname ##### # DCDIAG ## " " | Out-File -Encoding utf8 -filepath $logfile -Append " " | Out-File -Encoding utf8 -filepath $logfile -Append " " | Out-File -Encoding utf8 -filepath $logfile -Append "Schritt 1/7: Verzeichnisserverdiagnose `"dcdiag`"" | Out-File -Encoding utf8 -filepath $logfile -Append "----------" | Out-File -Encoding utf8 -filepath $logfile -Append foreach ($domain_dc in $domain_dcs) {$check = invoke-command -computername $domain_dc.hostname {dcdiag | Select-String "nicht bestanden"} if ($check -eq $null) { "TEST BESTANDEN: DC-Diag auf `""+$domain_dc.hostname+"`" hat keine Fehler ausgegeben." | Out-File -Encoding utf8 -filepath $logfile -Append } Else { "FEHLER: DC-Diag auf `""+$domain_dc+"`" hat eine Fehlermeldung verursacht!" | Out-File -Encoding utf8 -filepath $logfile -Append } " " | Out-File -Encoding utf8 -filepath $logfile -Append } ##### # REPLIKATION ## " " | Out-File -Encoding utf8 -filepath $logfile -Append " " | Out-File -Encoding utf8 -filepath $logfile -Append " " | Out-File -Encoding utf8 -filepath $logfile -Append "Schritt 2/7: Replikation prüfen `"repadmin /replsum`"" | Out-File -Encoding utf8 -filepath $logfile -Append "---------- " | Out-File -Encoding utf8 -filepath $logfile -Append " " | Out-File -Encoding utf8 -filepath $logfile -Append $check=$false " " | Out-File -Encoding utf8 -filepath $logfile -Append $replicats = Get-ADReplicationPartnerMetadata -Target * -Partition * | Select-Object server,partner,partition,lastreplicationattempt,lastreplicationsuccess,lastreplicationresult $check=$false $compare=(get-date).AddMinutes(-90) foreach ($replicat in $replicats) { if (($replicat.lastreplicationresult -notlike 0) -or ($replicat.lastreplicationsuccess -lt $compare)) { "FEHLER: Server:"+$replicat.server+", Partition: "+$replicat.partition+", zuletzt erfogreich: "+$replicat.lastreplicationsuccess+", letztes Ergebnis: "+$replicat.lastreplicationresult | Out-File -Encoding utf8 -filepath $logfile -Append $check=$true } } if ($check -eq $false) { "TEST BESTANDEN: Bei der Replikation wurden keine Fehler oder Verzögerungen festgestellt." | Out-File -Encoding utf8 -filepath $logfile -Append } ##### # BETRIEBSMASTER ## " " | Out-File -Encoding utf8 -filepath $logfile -Append " " | Out-File -Encoding utf8 -filepath $logfile -Append " " | Out-File -Encoding utf8 -filepath $logfile -Append "Schritt 3/7: Betriebsmaster-Rollen prüfen" | Out-File -Encoding utf8 -filepath $logfile -Append "---------- " | Out-File -Encoding utf8 -filepath $logfile -Append "Alle Rollen sollen auf dem `"DC-ESSEN-01`" liegen!" | Out-File -Encoding utf8 -filepath $logfile -Append " " | Out-File -Encoding utf8 -filepath $logfile -Append #Get-ADDomainController -Filter *| %{$_.Name + ": " + $_.OperationMasterRoles} | Out-File -Encoding utf8 -filepath $logfile -Append foreach ($domain_dc in $domain_dcs) { $check=Get-ADDomainController $domain_dc.hostname | Select-Object OperationMasterRoles if ($domain_dc.hostname -like "DC-ESSEN-01.secunet.de") { if ($check.OperationMasterRoles.Count -like "5") { "TEST BESTANDEN: `""+$domain_dc.hostname+"`" hat "+$check.OperationMasterRoles.Count+" Rollen zugewisen" | Out-File -Encoding utf8 -filepath $logfile -Append } Else { "FEHLER: `""+$domain_dc.hostname+"`" hat "+$check.OperationMasterRoles.Count+" Rollen zugewisen" | Out-File -Encoding utf8 -filepath $logfile -Append } } Else { if ($check.OperationMasterRoles.Count -like "0") { "TEST BESTANDEN: `""+$domain_dc.hostname+"`" hat "+$check.OperationMasterRoles.Count+" Rollen zugewisen" | Out-File -Encoding utf8 -filepath $logfile -Append } Else { "FEHLER: `""+$domain_dc.hostname+"`" hat "+$check.OperationMasterRoles.Count+" Rollen zugewisen" | Out-File -Encoding utf8 -filepath $logfile -Append } } } ##### # ZEITEINSTELLUNGEN ## " " | Out-File -Encoding utf8 -filepath $logfile -Append " " | Out-File -Encoding utf8 -filepath $logfile -Append " " | Out-File -Encoding utf8 -filepath $logfile -Append "Schritt 4/7:Prüfen der lokalen Zeiteinstellungen" | Out-File -Encoding utf8 -filepath $logfile -Append "---------- " | Out-File -Encoding utf8 -filepath $logfile -Append " " | Out-File -Encoding utf8 -filepath $logfile -Append foreach ($domain_dc in $domain_dcs) { "Zeiteinstellungen auf: "+$domain_dc.hostname | Out-File -Encoding utf8 -filepath $logfile -Append $check = invoke-command -computername $domain_dc.hostname {get-itemproperty "HKLM:\SYSTEM\CurrentControlSet\services\W32Time\Parameters"} "System: "+$domain_dc.hostname+" - Time-Typ: "+$check.Type+" - NTP-Server: "+$check.NtpServer | Out-File -Encoding utf8 -filepath $logfile -Append if ($domain_dc.hostname -like "DC-ESSEN-01.secunet.de") { if (($check.type -like "NTP") -and ($check.NtpServer -like "pool.ntp.org")) { "TEST BESTANDEN: Zeiteinstellungen korrekt" | Out-File -Encoding utf8 -filepath $logfile -Append } Else { "FEHLER: Zeiteinstellungen nicht korrekt" | Out-File -Encoding utf8 -filepath $logfile -Append } } Else { If ($check.type -like "NT5DS") { "TEST BESTANDEN: Zeiteinstellungen korrekt" | Out-File -Encoding utf8 -filepath $logfile -Append } Else { "FEHLER: Zeiteinstellungen nicht korrekt" | Out-File -Encoding utf8 -filepath $logfile -Append } } " " | Out-File -Encoding utf8 -filepath $logfile -Append } ##### # Speicherplatz ## " " | Out-File -Encoding utf8 -filepath $logfile -Append " " | Out-File -Encoding utf8 -filepath $logfile -Append " " | Out-File -Encoding utf8 -filepath $logfile -Append "Schritt 5/7: Freien Speicherplatz auf Laufwerk C prüfen" | Out-File -Encoding utf8 -filepath $logfile -Append "----------" | Out-File -Encoding utf8 -filepath $logfile -Append " " | Out-File -Encoding utf8 -filepath $logfile -Append foreach ($domain_dc in $domain_dcs) { "Laufwerk `"C:\`" auf: "+$domain_dc.hostname | Out-File -Encoding utf8 -filepath $logfile -Append $check=invoke-command -computername $domain_dc.hostname {get-wmiobject win32_volume -Filter 'drivetype = 3' | Where-Object name -eq "C:\"} $size=($check.FreeSpace)/1000000000 If ($check.FreeSpace -gt 5000000000) { "TEST BESTANDEN: Ausreichend freier Speicher auf Partition `""+$check.name+"`" verfügbar,"+[System.Math]::Round($size, 0)+"GB" | Out-File -Encoding utf8 -filepath $logfile -Append } Else { "FEHLER: Der Verfügbare Speicher auf Partition `""+$check.name+"`" hat den Grenzwert von 5GB unterschritten. Aktuell sind nur noch "+[System.Math]::Round($size, 0)+"GB verfügbar." | Out-File -Encoding utf8 -filepath $logfile -Append } " " | Out-File -Encoding utf8 -filepath $logfile -Append } ##### # Eventlogs ## " " | Out-File -Encoding utf8 -filepath $logfile -Append " " | Out-File -Encoding utf8 -filepath $logfile -Append " " | Out-File -Encoding utf8 -filepath $logfile -Append "Schritt 6/7: Eventlogs prüfen" | Out-File -Encoding utf8 -filepath $logfile -Append "----------" | Out-File -Encoding utf8 -filepath $logfile -Append " " | Out-File -Encoding utf8 -filepath $logfile -Append "Es wird lediglich die Zahl aller Meldungen ausgegeben, sowie die Zahl der Fehler pro Log." | Out-File -Encoding utf8 -filepath $logfile -Append "Sollten Fehler angezeigt werden, diese bitte prüfen, ggf. beheben und danach das entsprechende Log speichern und löschen" | Out-File -Encoding utf8 -filepath $logfile -Append "!Leere Eventlogs können nicht durchsucht werden, wordurch es zu Fehlermeldungen bei der Skriptausführung kommt!" | Out-File -Encoding utf8 -filepath $logfile -Append " " | Out-File -Encoding utf8 -filepath $logfile -Append $check=$false foreach ($domain_dc in $domain_dcs) { " " | Out-File -Encoding utf8 -filepath $logfile -Append "---Eventlogs auf: "+$domain_dc.hostname | Out-File -Encoding utf8 -filepath $logfile -Append # $Protokoll="Active Directory Web Services" $Count = (invoke-command -computername $domain_dc.hostname {Get-EventLog "Active Directory Web Services"}).count $ErrorCount = (invoke-command -computername $domain_dc.hostname {Get-EventLog "Active Directory Web Services" | where-object entrytype -match error}).count "Protokoll: `"Active Directory Web Services`" - Meldungen insgesamt: "+$count+", davon Fehler: "+$ErrorCount | Out-File -Encoding utf8 -filepath $logfile -Append If ($ErrorCount -notlike "0") { "FEHLER: Das Protokoll `"Active Directory Web Services`" auf `""+$domain_dc.hostname+"`" muss manuell geprüft werden!" | Out-File -Encoding utf8 -filepath $logfile -Append $check=$true } # $Protokoll="Application" $Count = (invoke-command -computername $domain_dc.hostname {Get-EventLog "Application"}).count $ErrorCount = (invoke-command -computername $domain_dc.hostname {Get-EventLog "Application" | where-object entrytype -match error}).count "Protokoll: `"Application`" - Meldungen insgesamt: "+$count+", davon Fehler: "+$ErrorCount | Out-File -Encoding utf8 -filepath $logfile -Append If ($ErrorCount -notlike "0") { "FEHLER: Das Protokoll `"Application`" auf `""+$domain_dc.hostname+"`" muss manuell geprüft werden!" | Out-File -Encoding utf8 -filepath $logfile -Append $check=$true } # $Protokoll="DFS Replication" $Count = (invoke-command -computername $domain_dc.hostname {Get-EventLog "DFS Replication"}).count $ErrorCount = (invoke-command -computername $domain_dc.hostname {Get-EventLog "DFS Replication" | where-object entrytype -match error}).count "Protokoll: `"DFS Replication`" - Meldungen insgesamt: "+$count+", davon Fehler: "+$ErrorCount | Out-File -Encoding utf8 -filepath $logfile -Append If ($ErrorCount -notlike "0") { "FEHLER: Das Protokoll `"DFS Replication`" auf `""+$domain_dc.hostname+"`" muss manuell geprüft werden!" | Out-File -Encoding utf8 -filepath $logfile -Append $check=$true } # $Protokoll="Directory Service" $Count = (invoke-command -computername $domain_dc.hostname {Get-EventLog "Directory Service"}).count $ErrorCount = (invoke-command -computername $domain_dc.hostname {Get-EventLog "Directory Service" | where-object entrytype -match error}).count "Protokoll: `"Directory Service`" - Meldungen insgesamt: "+$count+", davon Fehler: "+$ErrorCount | Out-File -Encoding utf8 -filepath $logfile -Append If ($ErrorCount -notlike "0") { "FEHLER: Das Protokoll `"Directory Service`" auf `""+$domain_dc.hostname+"`" muss manuell geprüft werden!" | Out-File -Encoding utf8 -filepath $logfile -Append $check=$true } # $Protokoll="DNS Server" $Count = (invoke-command -computername $domain_dc.hostname {Get-EventLog "DNS Server"}).count $ErrorCount = (invoke-command -computername $domain_dc.hostname {Get-EventLog "DNS Server" | where-object entrytype -match error}).count "Protokoll: `"DNS Server`" - Meldungen insgesamt: "+$count+", davon Fehler: "+$ErrorCount | Out-File -Encoding utf8 -filepath $logfile -Append If ($ErrorCount -notlike "0") { "FEHLER: Das Protokoll `"Active Directory Web Services`" auf `""+$domain_dc.hostname+"`" muss manuell geprüft werden!" | Out-File -Encoding utf8 -filepath $logfile -Append $check=$true } <# # $Protokoll="Security" $Count = (invoke-command -computername $domain_dc.hostname {Get-EventLog "Security"}).count $ErrorCount = (invoke-command -computername $domain_dc.hostname {Get-EventLog "Security" | where-object entrytype -match error}).count "Protokoll: `"Security`" - Meldungen insgesamt: "+$count+", davon Fehler: "+$ErrorCount | Out-File -Encoding utf8 -filepath $logfile -Append If ($ErrorCount -notlike "0") { "FEHLER! Das Protokoll `"DNS Server`" auf `""+$domain_dc.hostname+"`" muss manuell geprüft werden!" | Out-File -Encoding utf8 -filepath $logfile -Append $check=$true } #> # $Protokoll="System" $Count = (invoke-command -computername $domain_dc.hostname {Get-EventLog "System"}).count $ErrorCount = (invoke-command -computername $domain_dc.hostname {Get-EventLog "System" | where-object entrytype -match error}).count "Protokoll: `"System`" - Meldungen insgesamt: "+$count+", davon Fehler: "+$ErrorCount | Out-File -Encoding utf8 -filepath $logfile -Append If ($ErrorCount -notlike "0") { "FEHLER: Das Protokoll `"System`" auf `""+$domain_dc.hostname+"`" muss manuell geprüft werden!" | Out-File -Encoding utf8 -filepath $logfile -Append $check=$true } # $Protokoll="Windows PowerShell" $Count = (invoke-command -computername $domain_dc.hostname {Get-EventLog "Windows PowerShell"}).count $ErrorCount = (invoke-command -computername $domain_dc.hostname {Get-EventLog "Windows PowerShell" | where-object entrytype -match error}).count "Protokoll: `"Windows PowerShell`" - Meldungen insgesamt: "+$count+", davon Fehler: "+$ErrorCount | Out-File -Encoding utf8 -filepath $logfile -Append If ($ErrorCount -notlike "0") { "FEHLER: Das Protokoll `"Windows PowerShell`" auf `""+$domain_dc.hostname+"`" muss manuell geprüft werden!" | Out-File -Encoding utf8 -filepath $logfile -Append $check=$true } } if ($check -eq $false) { " " | Out-File -Encoding utf8 -filepath $logfile -Append "TEST BESTADNEN: Es wurden keine Fehler gefunden." | Out-File -Encoding utf8 -filepath $logfile -Append } ##### # Global Catalog ## " " | Out-File -Encoding utf8 -filepath $logfile -Append " " | Out-File -Encoding utf8 -filepath $logfile -Append " " | Out-File -Encoding utf8 -filepath $logfile -Append "Schritt 7/7: Prüfen, ob jeder DC die Rolle des Globalen Katalogs zugewiesen hat:" | Out-File -Encoding utf8 -filepath $logfile -Append "---------- " | Out-File -Encoding utf8 -filepath $logfile -Append " " | Out-File -Encoding utf8 -filepath $logfile -Append foreach ($domain_dc in $domain_dcs) { $check=Get-ADDomainController dc-essen-01 | select-object name,isglobalcatalog if ($check.isglobalcatalog -eq $true) { "TEST BESTANDEN: `""+$domain_dc.hostname+"`" hat die Rolle `"GC`" zugewiesen" | Out-File -Encoding utf8 -filepath $logfile -Append } Else { "FEHLER: `""+$domain_dc.hostname+"`" hat die Rolle `"GC`" nicht zugewiesen" | Out-File -Encoding utf8 -filepath $logfile -Append } } $stop=Get-Date -Format "dddd, dd.MM.yyy H:mm:ss" " " | Out-File -Encoding utf8 -filepath $logfile -Append " " | Out-File -Encoding utf8 -filepath $logfile -Append " " | Out-File -Encoding utf8 -filepath $logfile -Append "Domaincheck beendet um: "+$stop | Out-File -Encoding utf8 -filepath $logfile -Append #Stop-Transcript ##### # Ergebnisse per Mail versenden ## Send-MailMessage -SmtpServer "$SmtpServer" -from "$SmtpSender" -to "$SmtpRecipient" -Subject "AD-Healthcheck vom $start`: Prüfung durchgeführt" -body "Im Anhang befindet sich eine bereinigte Auswertung.`nBei Hinweisen auf Fehler ist eine weitere Analyse auf den betroffenen Systemen erforderlich.`n`nDie Eventlogs sollten regelmäßig geprüft und danach gesichert und gelöscht werden." -Attachments "$logfile" -Encoding utf8
powershell/ad/healthcheck.txt · Zuletzt geändert: 2024/05/27 08:36 von 127.0.0.1
