Benutzer-Werkzeuge

Webseiten-Werkzeuge


powershell:ad:healthcheck

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

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki