Leider gibt es heutzutage immer noch massenhaft Anwendungen, welche frisch fröhlich ihre Logfiles auf die Festplatte schreiben als gäbe es kein Morgen mehr. Dies hat zur Folge, dass der Platz auf der Festplatte immer weiter schrumpft und im ungünstigsten Fall, wenn es sich um die Systemplatte handelt, der ganze Server nicht mehr starten kann.

logrotate_screenshot.png

Um dem entgegen zu wirken habe ich ein kleines Script erstellt, welches alle Dateien welche älter als X Tage sind in komprimierten Archiven nach Monat ablegt. Die Monate wiederum in Ordner als Jahr abgelegt. Weiter löscht das Script alle Archiv Dateien, welcher älter als Y Tage sind. Somit haben wir die Logfiles welche jünger als X Tage sind im Klartext, alle die älter als X Tage sind komprimiert in Monats Archiven und alles was älter als Y Tage ist gar nicht mehr.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
<#
.SYNOPSIS
  Moves Logfiles to archive packages for amount of time

.DESCRIPTION
  Moves logfiles older than specified days to monthly archives. Deletes archives older than archive retention days.

.PARAMETER Path
  Path to the folder where the logfiles are

.PARAMETER ArchivesRoot
  Path where the archives shall be stored. Defaults to $Path\Archives

.PARAMETER RetentionDays
  Number of days to skip archiving for. Defaults to 30

.PARAMETER RetentionArchiveDays
  Number of days which trigger an archive to be deleted if older. Defaults to 365

.INPUTS
  Path of the logfile folder

.OUTPUTS
  Reorganized Logfiles folder

.NOTES
  Author: Philipp R
  Version: 1.0
  Last Modify: 01.04.2020

.EXAMPLE
  .\LogArchiver.ps1 -Path C:\my\logs
#>
#Requires -Version 4

Param(
    [Parameter(Mandatory=$true, ValueFromPipeline=$true)][string]$Path,
    [string]$ArchivesRoot = "$Path\Archives",
    [int]$RetentionDays = 30,
    [int]$RetentionArchiveDays = 365
)

Begin{
    if(-not(Test-Path $Path)){
        Write-Host -ForegroundColor Red "Path not found, $Path"
        return
    }
}

Process{
    $CompressionCandidates = Get-ChildItem $Path -File | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-$RetentionDays)}
    try{
        $CompressionCandidates | 
        Group-Object -Property {$_.LastWriteTime.Year} | ForEach-Object {
            $Year = $_.Name
            $_.Group | Group-Object -Property {$_.LastWriteTime.Month} | ForEach-Object {
                $TargetArchive = "$ArchivesRoot\$Year\$($_.Name).zip"
                # Create the year folder
                $null = New-Item -ItemType Directory -Path (Split-Path $TargetArchive) -ErrorAction SilentlyContinue
                # if archive exists add it otherwise create new
                $_.Group | Compress-Archive -Update:(Test-Path $TargetArchive) -DestinationPath $TargetArchive
            }
        }
        # Only remove files if we successfully archived them
        $CompressionCandidates | Select-Object -ExpandProperty FullName |  Remove-Item  -Force
    }
    catch {
        Write-Host -ForegroundColor Red "Something strange happened"
        $_.Exception
    }

    # Remove old archives
    $DueDate = (Get-Date).AddDays(-$RetentionArchiveDays)
    Get-ChildItem $ArchivesRoot | Where-Object { [int]($_.Name) -lt [int]($DueDate.Year) } | Select-Object -ExpandProperty FullName | Remove-Item -Recurse -Force
    Get-ChildItem "$ArchivesRoot\$($DueDate.Year)" | Where-Object { [int]($_.Name.Split(".")[0]) -lt $DueDate.Month } | Select-Object -ExpandProperty FullName | Remove-Item -Recurse -Force
}

End{

}