Exchange 2016 oder Exchange 2019 entrümpeln
Nach so einigen Installationen von z.B. kumulativen Updates oder auch diversen Sicherheitsupdates, verbleiben die alten OWA Versionen (Exchange-Buildnummern) im Installationsordner. Da können sich gut und gerne mal über 50 GB ansammeln.
Clean up Exchange Folder
Bei der Bereinigung achte ich darauf, das immer die letzten 3 vorherigen Versionen auf dem System erhalten bleiben. Der “prem” Ordner ist, sofern er nicht individuell angepasst wurde, hier zu finden:
“C:\Program Files\Microsoft\Exchange Server\V15\ClientAccess\Owa\prem”
%ExchangeInstallPath%ClientAccess\Owa\prem
Der “Fonts” Ordner sowie die letzten 3 Versionen bleiben erhalten, der Rest kann gelöscht werden.
Cleanup logs older than the set of days in numbers
Exchange alte Logs bereinigen
# Cleanup logs older than the set of days in numbers
$Days = 5
# Path of the logs that you like to cleanup
$IISLogPath = “C:\inetpub\logs\LogFiles\”
$ExchangeLoggingPath = “C:\Program Files\Microsoft\Exchange Server\V15\Logging\”
$ETLLoggingPath = “C:\Program Files\Microsoft\Exchange Server\V15\Bin\Search\Ceres\Diagnostics\ETLTraces\”
$ETLLoggingPath2 = “C:\Program Files\Microsoft\Exchange Server\V15\Bin\Search\Ceres\Diagnostics\Logs\”
$UnifiedContentPath = “C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles\data\Temp\UnifiedContent”
# Test if evelated Shell
Function Confirm-Administrator {
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal( [Security.Principal.WindowsIdentity]::GetCurrent() )
if ($currentPrincipal.IsInRole( [Security.Principal.WindowsBuiltInRole]::Administrator )) {
return $true
} else {
return $false
}
}
if (-not (Confirm-Administrator)) {
Write-Output $msgNewLine
Write-Warning “This script needs to be executed in elevated mode. Start the Exchange Management Shell as an Administrator and try again.”
$Error.Clear()
Start-Sleep -Seconds 2
exit
}
# Get size of all logfiles
Function Get-LogfileSize ($TargetFolder) {
if (Test-Path $TargetFolder) {
$Now = Get-Date
$LastWrite = $Now.AddDays(-$days)
$Files = Get-ChildItem $TargetFolder -Recurse | Where-Object { $_.Name -like “*.log” -or $_.Name -like “*.blg” -or $_.Name -like “*.etl” } | Where-Object { $_.lastWriteTime -le “$lastwrite” }
$SizeGB = ($Files | Measure-Object -Sum Length).Sum / 1GB
$SizeGBRounded = [math]::Round($SizeGB,2)
return $SizeGBRounded
}
Else {
Write-Output “The folder $TargetFolder doesn’t exist! Check the folder path!”
}
}
Function Get-UnifiedContentfileSize ($TargetFolder) {
if (Test-Path $TargetFolder) {
$Now = Get-Date
$LastWrite = $Now.AddDays(-$days)
$Files = Get-ChildItem $TargetFolder -Recurse | Where-Object { $_.lastWriteTime -le “$lastwrite” }
$SizeGB = ($Files | Measure-Object -Sum Length).Sum / 1GB
$SizeGBRounded = [math]::Round($SizeGB,2)
return $SizeGBRounded
}
Else {
Write-Output “The folder $TargetFolder doesn’t exist! Check the folder path!”
}
}
# Remove the logs
Function Remove-Logfiles ($TargetFolder) {
if (Test-Path $TargetFolder) {
$Now = Get-Date
$LastWrite = $Now.AddDays(-$days)
$Files = Get-ChildItem $TargetFolder -Recurse | Where-Object { $_.Name -like “*.log” -or $_.Name -like “*.blg” -or $_.Name -like “*.etl” } | Where-Object { $_.lastWriteTime -le “$lastwrite” }
$FileCount = $Files.Count
$Files | Remove-Item -force -ea 0
return $FileCount
}
Else {
Write-Output “The folder $TargetFolder doesn’t exist! Check the folder path!”
}
}
Function Remove-UnifiedContent ($TargetFolder) {
if (Test-Path $TargetFolder) {
$Now = Get-Date
$LastWrite = $Now.AddDays(-$days)
$Files = Get-ChildItem $TargetFolder -Recurse | Where-Object { $_.lastWriteTime -le “$lastwrite” }
$FileCount = $Files.Count
$Files | Remove-Item -force -ea 0
return $FileCount
}
Else {
Write-Output “The folder $TargetFolder doesn’t exist! Check the folder path!”
}
}
# Get logs and traces and write some stats
$IISLogSize = Get-LogfileSize $IISLogPath
$ExchangeLogSize = Get-LogfileSize $ExchangeLoggingPath
$ETL1LogSize = Get-LogfileSize $ETLLoggingPath
$ETL2LogSize = Get-LogfileSize $ETLLoggingPath2
$UnifiedContentSize = Get-UnifiedContentfileSize $UnifiedContentPath
$TotalLogSize = $IISLogSize + $ExchangeLogSize + $ETL1LogSize + $ETL2LogSize + $UnifiedContentSize
write-host “Total Log and Trace File Size is $TotalLogSize GB”
#Ask if script should realy delete the logs
$Confirmation = Read-Host “Delete Exchange Server log and trace files? [y/n]”
while($Confirmation -notmatch “[yYnN]”) {
if ($Confirmation -match “[nN]”) {exit}
$Confirmation = Read-Host “Delete Exchange Server log and trace files? [y/n]”
}
# Delete logs (if confirmed) and write some stats
if ($Confirmation -match “[yY]”) {
$DeleteIISFiles = Remove-Logfiles $IISLogPath
$DeleteExchangeLogs = Remove-Logfiles $ExchangeLoggingPath
$DeleteETL1Logs = Remove-Logfiles $ETLLoggingPath
$DeleteETL2Logs = Remove-Logfiles $ETLLoggingPath2
$DeleteUnifiedContent = Remove-UnifiedContent $UnifiedContentPath
$TotalDeletedFiles = $DeleteIISFiles + $DeleteExchangeLogs + $DeleteETL1Logs + $DeleteETL2Logs + $DeleteUnifiedContent
write-host “$TotalDeletedFiles files deleted”
}
https://www.der-windows-papst.de/2021/10/05/exchange-circular-logging/