Log-Manager.ps1

<#PSScriptInfo
 
.VERSION 22.06.01
 
.GUID 109eb5a2-1dd4-4def-9b9e-1d7413c8697f
 
.AUTHOR Mike Galvin Contact: mike@gal.vin / twitter.com/mikegalvin_ / discord.gg/5ZsnJ5k
 
.COMPANYNAME Mike Galvin
 
.COPYRIGHT (C) Mike Galvin. All rights reserved.
 
.TAGS Log Manager Clean up Backup Zip History MDT Microsoft Deployment Toolkit IIS Internet Information Services
 
.LICENSEURI
 
.PROJECTURI https://gal.vin/utils/log-manager-utility/
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
 
#>


<#
    .SYNOPSIS
    Log Manager Utility - Flexible clean up and backup of log files.
 
    .DESCRIPTION
    Delete files and folders older than X days, or backup files and folders older than X days to another location and then remove files.
    Run with -help or no arguments for usage.
#>


## Set up command line switches.
[CmdletBinding()]
Param(
    [alias("LogsPath")]
    $SourceUsr,
    [alias("LogKeep")]
    $LogHistory,
    [alias("BackupTo")]
    $BackupUsr,
    [alias("BacKeep")]
    $BacHistory,
    [alias("Wd")]
    $WorkDirUsr,
    [alias("ZipName")]
    $ZName,
    [alias("L")]
    $LogPathUsr,
    [alias("LogRotate")]
    $LogManOwnHistory,
    [alias("Subject")]
    $MailSubject,
    [alias("SendTo")]
    $MailTo,
    [alias("From")]
    $MailFrom,
    [alias("Smtp")]
    $SmtpServer,
    [alias("Port")]
    $SmtpPort,
    [alias("User")]
    $SmtpUser,
    [alias("Pwd")]
    [ValidateScript({Test-Path -Path $_ -PathType Leaf})]
    $SmtpPwd,
    [switch]$UseSsl,
    [switch]$Compress,
    [switch]$Sz,
    [switch]$Help,
    [switch]$NoBanner)

If ($NoBanner -eq $False)
{
    Write-Host -ForegroundColor Yellow -BackgroundColor Black -Object "
         __ _____ ___ __ __ __ _ _ __ ___ ____ ____
        ( ) ( _ )/ __) ( \/ ) /__\ ( \( ) /__\ / __)( ___)( _ \
         )(__ )(_)(( (_-. ) ( /(__)\ ) ( /(__)\( (_-. )__) ) /
        (____)(_____)\___/ (_/\/\_)(__)(__)(_)\_)(__)(__)\___/(____)(_)\_)
         __ __ ____ ____ __ ____ ____ _ _
        ( )( )(_ _)(_ _)( ) (_ _)(_ _)( \/ ) Mike Galvin
         )(__)( )( _)(_ )(__ _)(_ )( \ / https://gal.vin
        (______) (__) (____)(____)(____) (__) (__)
                                                        Version 22.06.01
                                                       See -help for usage
                                                                                
                    Donate: https://www.paypal.me/digressive
"

}

If ($PSBoundParameters.Values.Count -eq 0 -or $Help)
{
    Write-Host -Object "PLEASE NOTE! This tool can be destructive! Please test it on non critical files first!
Usage:
    From a terminal run: [path\]Log-Manager.ps1 -LogsPath [path\] -LogKeep [number] -BackupTo [path\]
    This will backup and remove logs in the path specified older than X days.
 
    Use -BacKeep [number] option to specify how long to keep the backups.
    Use -Compress to create a zip file of the logs that are being backed up.
    Use -Sz to use 7-Zip to create a zip instead of Windows compression.
    7-Zip must be installed in the default location, if it is not found, Windows compression will be used.
 
    Use -Wd [path\] to specify a 'working directory' for the creation of the zip file.
    Use -ZipName [name] to name the zip file as you wish - the time and date will be appended to this name.
    If this left blank a default name of logs-HOSTNAME-date-time.zip will be used.
 
    To output a log: -L [path\].
    To remove logs produced by the utility older than X days: -LogRotate [number].
    Run with no ASCII banner: -NoBanner
 
    To use the 'email log' function:
    Specify the subject line with -Subject ""'[subject line]'"" If you leave this blank a default subject will be used
    Make sure to encapsulate it with double & single quotes as per the example for Powershell to read it correctly.
 
    Specify the 'to' address with -SendTo [example@contoso.com]
    For multiple address, separate with a comma.
 
    Specify the 'from' address with -From [example@contoso.com]
    Specify the SMTP server with -Smtp [smtp server name]
 
    Specify the port to use with the SMTP server with -Port [port number].
    If none is specified then the default of 25 will be used.
 
    Specify the user to access SMTP with -User [example@contoso.com]
    Specify the password file to use with -Pwd [path\]ps-script-pwd.txt.
    Use SSL for SMTP server connection with -UseSsl.
 
    To generate an encrypted password file run the following commands
    on the computer and the user that will run the script:
"

    Write-Host -Object ' $creds = Get-Credential
    $creds.Password | ConvertFrom-SecureString | Set-Content [path\]ps-script-pwd.txt'

}

else {
    ## If logging is configured, start logging.
    ## If the log file already exists, clear it.
    If ($LogPathUsr)
    {
        ## Clean User entered string
        $LogPath = $LogPathUsr.trimend('\')

        ## Make sure the log directory exists.
        If ((Test-Path -Path $LogPath) -eq $False)
        {
            New-Item $LogPath -ItemType Directory -Force | Out-Null
        }

        $LogFile = ("Log-Man_{0:yyyy-MM-dd_HH-mm-ss}.log" -f (Get-Date))
        $Log = "$LogPath\$LogFile"

        If (Test-Path -Path $Log)
        {
            Clear-Content -Path $Log
        }
    }

    ##
    ## Start of functions.
    ##
    ## Function to get date in specific format.
    Function Get-DateFormat
    {
        Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    }

    ## Function for logging.
    Function Write-Log($Type, $Evt)
    {
        If ($Type -eq "Info")
        {
            If ($LogPathUsr)
            {
                Add-Content -Path $Log -Encoding ASCII -Value "$(Get-DateFormat) [INFO] $Evt"
            }
            
            Write-Host -Object "$(Get-DateFormat) [INFO] $Evt"
        }

        If ($Type -eq "Succ")
        {
            If ($LogPathUsr)
            {
                Add-Content -Path $Log -Encoding ASCII -Value "$(Get-DateFormat) [SUCCESS] $Evt"
            }

            Write-Host -ForegroundColor Green -Object "$(Get-DateFormat) [SUCCESS] $Evt"
        }

        If ($Type -eq "Err")
        {
            If ($LogPathUsr)
            {
                Add-Content -Path $Log -Encoding ASCII -Value "$(Get-DateFormat) [ERROR] $Evt"
            }

            Write-Host -ForegroundColor Red -BackgroundColor Black -Object "$(Get-DateFormat) [ERROR] $Evt"
        }

        If ($Type -eq "Conf")
        {
            If ($LogPathUsr)
            {
                Add-Content -Path $Log -Encoding ASCII -Value "$Evt"
            }

            Write-Host -ForegroundColor Cyan -Object "$Evt"
        }
    }

    ## Function for the options post backup.
    Function OptionsRun
    {
        ## If the -keep switch AND the -compress switch are NOT configured.
        If ($Null -eq $BacHistory -And $Compress -eq $False)
        {
            ## Remove all previous backup folders, including ones from previous versions of this script.
            try {
                Get-ChildItem -Path $WorkDir -Filter "$ZName-*-*-***-*-*" -Directory | Remove-Item -Recurse -Force
            }
            catch {
                $_.Exception.Message | Write-Log -Type Err -Evt $_
            }

            ## If a working directory is configured by the user, remove all previous backup folders, including
            ## ones from previous versions of this script.
            If ($WorkDir -ne $Backup)
            {
                try {
                    Get-ChildItem -Path $Backup -Filter "$ZName-*-*-***-*-*" -Directory | Remove-Item -Recurse -Force
                }
                catch {
                    $_.Exception.Message | Write-Log -Type Err -Evt $_
                }
            }

            Write-Log -Type Info -Evt "Removing previous backup folders"
        }

        ## If the -keep option IS configured AND the -compress option is NOT configured.
        else {
            If ($Compress -eq $False)
            {
                ## Remove previous backup folders older than the configured number of days, including
                ## ones from previous versions of this script.
                try {
                    Get-ChildItem -Path $WorkDir -Filter "$ZName-*-*-***-*-*" -Directory | Where-Object CreationTime -lt (Get-Date).AddDays(-$BacHistory) | Remove-Item -Recurse -Force
                }
                catch {
                    $_.Exception.Message | Write-Log -Type Err -Evt $_
                }

                ## If a working directory is configured by the user, remove previous backup folders
                ## older than the configured number of days remove all previous backup folders,
                ## including ones from previous versions of this script.
                If ($WorkDir -ne $Backup)
                {
                    try {
                        Get-ChildItem -Path $Backup -Filter "$ZName-*-*-***-*-*" -Directory | Where-Object CreationTime -lt (Get-Date).AddDays(-$BacHistory) | Remove-Item -Recurse -Force
                    }
                    catch {
                        $_.Exception.Message | Write-Log -Type Err -Evt $_
                    }
                }

                Write-Log -Type Info -Evt "Removing backup folders older than: $BacHistory days"
            }
        }

        ## Check to see if the -compress switch IS configured AND if the -keep switch is NOT configured.
        If ($Compress)
        {
            If ($Null -eq $BacHistory)
            {
                ## Remove all previous compressed backups, including ones from previous versions of this script.
                try {
                    Remove-Item "$WorkDir\$ZName-*-*-***-*-*.zip" -Force
                }
                catch {
                    $_.Exception.Message | Write-Log -Type Err -Evt $_
                }

                ## If a working directory is configured by the user, remove all previous compressed backups,
                ## including ones from previous versions of this script.
                If ($WorkDir -ne $Backup)
                {
                    try {
                        Remove-Item "$Backup\$ZName-*-*-***-*-*.zip" -Force
                    }
                    catch {
                        $_.Exception.Message | Write-Log -Type Err -Evt $_
                    }
                }

                Write-Log -Type Info -Evt "Removing previous compressed backups"
            }

            ## If the -compress switch IS configured AND if the -keep switch IS configured.
            else {
                ## Remove previous compressed backups older than the configured number of days, including
                ## ones from previous versions of this script.
                try {
                    Get-ChildItem -Path "$WorkDir\$ZName-*-*-***-*-*.zip" | Where-Object CreationTime -lt (Get-Date).AddDays(-$BacHistory) | Remove-Item -Force
                }
                catch {
                    $_.Exception.Message | Write-Log -Type Err -Evt $_
                }

                ## If a working directory is configured by the user, remove previous compressed backups older
                ## than the configured number of days, including ones from previous versions of this script.
                If ($WorkDir -ne $Backup)
                {
                    try {
                        Get-ChildItem -Path "$Backup\$ZName-*-*-***-*-*.zip" | Where-Object CreationTime -lt (Get-Date).AddDays(-$BacHistory) | Remove-Item -Force
                    }
                    catch {
                        $_.Exception.Message | Write-Log -Type Err -Evt $_
                    }
                }

                Write-Log -Type Info -Evt "Removing compressed backups older than: $BacHistory days"
            }

            ## If the -compress switch and the -Sz switch IS configured, test for 7zip being installed.
            ## If it is, compress the backup folder, if it is not use Windows compression.
            If ($Sz -eq $True)
            {
                If (Test-Path -Path "$env:programfiles\7-Zip\7z.exe")
                {
                    Write-Log -Type Info -Evt "Compressing using 7-Zip compression"

                    try {
                        & "$env:programfiles\7-Zip\7z.exe" -bso0 a -tzip ("$WorkDir\$ZName-{0:yyyy-MM-dd_HH-mm-ss}.zip" -f (Get-Date)) "$WorkDir\$ZName\*"
                    }
                    catch {
                        $_.Exception.Message | Write-Log -Type Err -Evt $_
                    }
                }

                else {
                    Write-Log -Type Info -Evt "Compressing using Windows compression"
                    Add-Type -AssemblyName "system.io.compression.filesystem"
                    try {
                        [io.compression.zipfile]::CreateFromDirectory("$WorkDir\$ZName", ("$WorkDir\$ZName-{0:yyyy-MM-dd_HH-mm-ss}.zip" -f (Get-Date)))
                    }
                    catch {
                        $_.Exception.Message | Write-Log -Type Err -Evt $_
                    }
                }
            }

            ## If the -compress switch IS configured and the -Sz switch is NOT configured, compress
            ## the backup folder using Windows compression.
            else {
                Write-Log -Type Info -Evt "Compressing using Windows compression"
                Add-Type -AssemblyName "system.io.compression.filesystem"
                [io.compression.zipfile]::CreateFromDirectory("$WorkDir\$ZName", ("$WorkDir\$ZName-{0:yyyy-MM-dd_HH-mm-ss}.zip" -f (Get-Date)))
            }

            ## Clean up
            try {
                Get-ChildItem -Path $WorkDir -Filter "$ZName" -Directory | Remove-Item -Recurse -Force
            }
            catch {
                $_.Exception.Message | Write-Log -Type Err -Evt $_
            }

            ## If a working directory has been configured by the user, move the compressed
            ## backup to the backup location and rename to include the date.
            If ($WorkDir -ne $Backup)
            {
                try {
                    Get-ChildItem -Path $WorkDir -Filter "$ZName-*-*-*-*-*.zip" | Move-Item -Destination $Backup
                }
                catch {
                    $_.Exception.Message | Write-Log -Type Err -Evt $_
                }
            }
        }

        ## If the -compress switch is NOT configured AND if the -keep switch is NOT configured, rename
        ## the backup folder to include the date.
        else {
            try {
                Get-ChildItem -Path $WorkDir -Filter $ZName -Directory | Rename-Item -NewName ("$WorkDir\$ZName-{0:yyyy-MM-dd_HH-mm-ss}" -f (Get-Date))
            }
            catch {
                $_.Exception.Message | Write-Log -Type Err -Evt $_
            }

            If ($WorkDir -ne $Backup)
            {
                try {
                    Get-ChildItem -Path $WorkDir -Filter "$ZName-*-*-***-*-*" -Directory | Move-Item -Destination ("$Backup\$ZName-{0:yyyy-MM-dd_HH-mm-ss}" -f (Get-Date))
                }
                catch {
                    $_.Exception.Message | Write-Log -Type Err -Evt $_
                }
            }
        }
    }
    ##
    ## End of functions.
    ##

    ##
    ## Start main process.
    ##

    If ($Null -eq $SourceUsr)
    {
        Write-Log -Type Err -Evt "You must specify -LogsPath."
        Exit
    }

    else {
        ## Clean User entered string
        $Source = $SourceUsr.trimend('\')

        If ($Null -eq $BackupUsr -And $BacHistory)
        {
            Write-Log -Type Err -Evt "You must specify -BackupTo to use -BacKeep."
            Exit
        }

        If ($Null -eq $BackupUsr -And $WorkDirUsr)
        {
            Write-Log -Type Err -Evt "You must specify -BackupTo to use -Wd."
            Exit
        }

        If ($Compress -eq $false -And $Null -ne $ZName)
        {
            Write-Log -Type Err -Evt "You must specify -Compress to use -ZipName."
            Exit
        }

        If ($Compress -eq $false -And $Sz -eq $true)
        {
            Write-Log -Type Err -Evt "You must specify -Compress to use -Sz."
            Exit
        }

        If ($Compress -eq $true -And $Null -eq $BackupUsr)
        {
            Write-Log -Type Err -Evt "You must specify -BackupTo to use -Compress."
            Exit
        }

        ## Clean User entered string
        If ($BackupUsr)
        {
            $Backup = $BackupUsr.trimend('\')
        }

        If ($WorkDirUsr)
        {
            $WorkDir = $WorkDirUsr.trimend('\')
        }

        If ($Null -eq $LogPathUsr -And $SmtpServer)
        {
            Write-Log -Type Err -Evt "You must specify -L [path\] to use the email log function."
            Exit
        }
    }

    ## getting Windows Version info
    $OSVMaj = [environment]::OSVersion.Version | Select-Object -expand major
    $OSVMin = [environment]::OSVersion.Version | Select-Object -expand minor
    $OSVBui = [environment]::OSVersion.Version | Select-Object -expand build
    $OSV = "$OSVMaj" + "." + "$OSVMin" + "." + "$OSVBui"

    ##
    ## Display the current config and log if configured.
    ##
    Write-Log -Type Conf -Evt "************ Running with the following config *************."
    Write-Log -Type Conf -Evt "Utility Version:.......22.06.01"
    Write-Log -Type Conf -Evt "Hostname:..............$Env:ComputerName."
    Write-Log -Type Conf -Evt "Windows Version:.......$OSV."

    If ($SourceUsr)
    {
        Write-Log -Type Conf -Evt "Path to process:.......$SourceUsr."
    }

    If ($Null -ne $LogHistory)
    {
        Write-Log -Type Conf -Evt "Logs to keep:..........$LogHistory days"
    }

    If ($BackupUsr)
    {
        Write-Log -Type Conf -Evt "Backup directory:......$BackupUsr."
    }

    If ($WorkDirUsr)
    {
        Write-Log -Type Conf -Evt "Working directory:.....$WorkDirUsr."
    }

    If ($Null -ne $BacHistory)
    {
        Write-Log -Type Conf -Evt "Backups to keep:.......$BacHistory days"
    }

    If ($ZName)
    {
        Write-Log -Type Conf -Evt "Zip file name:.........$ZName + date and time."
    }

    If ($Compress)
    {
        Write-Log -Type Conf -Evt "-Compress switch is:...$Compress."
    }

    If ($Sz)
    {
        Write-Log -Type Conf -Evt "-Sz switch is:.........$Sz."
    }

    If ($LogPathUsr)
    {
        Write-Log -Type Conf -Evt "Log directory:.........$LogPath."
    }

    If ($Null -ne $LogManOwnHistory)
    {
        Write-Log -Type Conf -Evt "Logs to keep:..........$LogManOwnHistory days."
    }

    If ($MailTo)
    {
        Write-Log -Type Conf -Evt "E-mail log to:.........$MailTo."
    }

    If ($MailFrom)
    {
        Write-Log -Type Conf -Evt "E-mail log from:.......$MailFrom."
    }

    If ($MailSubject)
    {
        Write-Log -Type Conf -Evt "E-mail subject:........$MailSubject."
    }

    If ($SmtpServer)
    {
        Write-Log -Type Conf -Evt "SMTP server:...........$SmtpServer."
    }

    If ($SmtpPort)
    {
        Write-Log -Type Conf -Evt "SMTP Port:.............$SmtpPort."
    }

    If ($SmtpUser)
    {
        Write-Log -Type Conf -Evt "SMTP user:.............$SmtpUser."
    }

    If ($SmtpPwd)
    {
        Write-Log -Type Conf -Evt "SMTP pwd file:.........$SmtpPwd."
    }

    If ($SmtpServer)
    {
        Write-Log -Type Conf -Evt "-UseSSL switch is:.....$UseSsl."
    }
    Write-Log -Type Conf -Evt "************************************************************"
    Write-Log -Type Info -Evt "Process started"
    ##
    ## Display current config ends here.
    ##

    ## Count the number of files that are old enough to work on in the configured directory
    ## If the number of the files to work on is not zero then proceed.
    $FileNo = Get-ChildItem -Path $Source -Recurse | Where-Object CreationTime -lt (Get-Date).AddDays(-$LogHistory) | Measure-Object

    If ($FileNo.count -ne 0)
    {
        ## If time -days switch isn't configured, then set it to 0
        If ($Null -eq $LogHistory)
        {
            $LogHistory = "0"
        }

        If ($Null -eq $BacHistory)
        {
            $BacHistory = "0"
        }

        ## If the user has not configured the working directory, set it as the backup directory if needed.
        If ($BackupUsr)
        {
            ## Make sure the directory exists.
            If ((Test-Path -Path $Backup) -eq $False)
            {
                New-Item $Backup -ItemType Directory -Force | Out-Null
            }

            If ($Null -eq $WorkDirUsr)
            {
                $WorkDir = "$Backup"
            }
        }

        ## If the user has not configured a zip name, set it as the default.
        If ($Null -eq $ZName)
        {
            $ZName = "Logs-$env:computername"
        }

        Write-Log -Type Info -Evt "The following objects will be processed:"
        Get-ChildItem -Path $Source | Select-Object -ExpandProperty Name

        If ($LogPathUsr)
        {
            Get-ChildItem -Path $Source | Select-Object -ExpandProperty Name | Out-File -Append $Log -Encoding ASCII
        }

        If ($BackupUsr)
        {
            ## Test for the existence of a previous backup. If it exists, delete it.
            If (Test-Path -Path "$WorkDir\$ZName")
            {
                try {
                    Remove-Item "$WorkDir\$ZName" -Recurse -Force
                }
                catch {
                    $_.Exception.Message | Write-Log -Type Err -Evt $_
                }
            }

            Write-Log -Type Info -Evt "Attempting to move objects older than: $LogHistory days"

            try {
                New-Item -Path "$WorkDir\$ZName" -ItemType Directory | Out-Null
                Get-ChildItem -Path $Source | Where-Object CreationTime -lt (Get-Date).AddDays(-$LogHistory) | Copy-Item -Destination "$WorkDir\$ZName" -Recurse -Force
            }
            catch {
                $_.Exception.Message | Write-Log -Type Err -Evt $_
            }

            OptionsRun
        }

        ## If no backup options were configured, or after doing the previous operations, remove the old files.
        Get-ChildItem -Path $Source | Where-Object CreationTime -lt (Get-Date).AddDays(-$LogHistory) | Remove-Item -Recurse
        Write-Log -Type Info -Evt "Deleting logs older than: $LogHistory days"

        ##
        ## Main process ends here.
        ##
    }

    ## If there are no objects old enough to process then finish.
    else {
        Write-Log -Type Info -Evt "There are no objects to process."
    }

    Write-Log -Type Info -Evt "Process finished."

    If ($Null -ne $LogManOwnHistory)
    {
        ## Cleanup logs.
        Write-Log -Type Info -Evt "Deleting Log Manager logs older than: $LogManOwnHistory days"
        Get-ChildItem -Path "$LogPath\Log-Man_*" -File | Where-Object CreationTime -lt (Get-Date).AddDays(-$LogManOwnHistory) | Remove-Item -Recurse
    }

    ## This whole block is for e-mail, if it is configured.
    If ($SmtpServer)
    {
        If (Test-Path -Path $Log)
        {
            ## Default e-mail subject if none is configured.
            If ($Null -eq $MailSubject)
            {
                $MailSubject = "Log Manager Utility Log"
            }

            ## Default Smtp Port if none is configured.
            If ($Null -eq $SmtpPort)
            {
                $SmtpPort = "25"
            }

            ## Setting the contents of the log to be the e-mail body.
            $MailBody = Get-Content -Path $Log | Out-String

            ForEach ($MailAddress in $MailTo)
            {
                ## If an smtp password is configured, get the username and password together for authentication.
                ## If an smtp password is not provided then send the e-mail without authentication and obviously no SSL.
                If ($SmtpPwd)
                {
                    $SmtpPwdEncrypt = Get-Content $SmtpPwd | ConvertTo-SecureString
                    $SmtpCreds = New-Object System.Management.Automation.PSCredential -ArgumentList ($SmtpUser, $SmtpPwdEncrypt)

                    ## If -ssl switch is used, send the email with SSL.
                    ## If it isn't then don't use SSL, but still authenticate with the credentials.
                    If ($UseSsl)
                    {
                        Send-MailMessage -To $MailAddress -From $MailFrom -Subject $MailSubject -Body $MailBody -SmtpServer $SmtpServer -Port $SmtpPort -UseSsl -Credential $SmtpCreds
                    }

                    else {
                        Send-MailMessage -To $MailAddress -From $MailFrom -Subject $MailSubject -Body $MailBody -SmtpServer $SmtpServer -Port $SmtpPort -Credential $SmtpCreds
                    }
                }

                else {
                    Send-MailMessage -To $MailAddress -From $MailFrom -Subject $MailSubject -Body $MailBody -SmtpServer $SmtpServer -Port $SmtpPort
                }
            }
        }

        else {
            Write-Host -ForegroundColor Red -BackgroundColor Black -Object "There's no log file to email."
        }
    }
    ## End of Email block
}
## End