This PowerShell script is designed for situations where new files are written daily and the type of files might be reports or backups where you don’t need to keep them all, but you want to retain some for a period of time. The files are moved to subdirectories for daily, weekly and monthly. You specify how many daily, weekly or monthly files you want to keep.
#
Function Rotate-Logs {
<#
Public Domain License
.SYNOPSIS
Clean up and rotate files
.DESCRIPTION
This script rotates files and keeps them in three directories
\daily
\weekly
\monthly
New files are expected to be written to $LogDir and Rotate-Logs moves them into subdirectories
.EXAMPLE
Rotate-Logs -LogDir "c:\MyLogDirectory"
.LINKS
http://www.getsurreal.com/powershell/powershell-file-rotation
#>
Param (
[Parameter(Mandatory=$True,ValueFromPipeline=$false)]
[string]$LogDir, # Directory log files are written to
[Parameter(ValueFromPipeline=$false)]
[int]$DayOfWeek = 2, # The day of the week to store for weekly files (1 to 7 where 1 is Sunday)
[Parameter(ValueFromPipeline=$false)]
[int]$DayOfMonth = 1, # The day of the month to store for monthly files (Max = 28 since varying last day of month not currently handled)
[Parameter(ValueFromPipeline=$false)]
[int]$RotationDaily = 7, # The number of daily files to keep
[Parameter(ValueFromPipeline=$false)]
[int]$RotationWeekly = 6, # The number of weekly files to keep
[Parameter(ValueFromPipeline=$false)]
[int]$RotationMonthly = 5 # The number of monthly files to keep
)
Process {
if (-not $LogDir) {
Write-Host "Error: -LogDir not set"
Exit
}
$date = Get-Date
$verify_log_dir = Test-Path $LogDir
if ($verify_log_dir) {
$verify_daily_dir = Test-Path "$LogDir\daily"
$verify_weekly_dir = Test-Path "$LogDir\weekly"
$verify_monthly_dir = Test-Path "$LogDir\monthly"
# If the daily directory does not exist try to create it
if (!$verify_daily_dir) {
$md_daily = md -Name "daily" -Path $LogDir
if (!$md_daily){
Write-Host "Error setting up log directories. Check Permissions."
exit
}
}
# If the weekly directory does not exist try to create it
if (!$verify_weekly_dir) {
$md_weekly = md -Name "weekly" -Path $LogDir
if (!$md_weekly){
Write-Host "Error setting up log directories. Check Permissions."
exit
}
}
# If the monthly directory does not exist try to create it
if (!$verify_monthly_dir) {
$md_monthly = md -Name "monthly" -Path $LogDir
if (!$md_monthly){
Write-Host "Error setting up log directories. Check Permissions."
exit
}
}
}
else {
Write-Host "Error: Log directory $LogDir does not exist."
exit
}
$logs_root = Get-ChildItem $LogDir | where {$_.Attributes -ne "Directory"}
if ($logs_root) {
foreach ($file in $logs_root) {
$file_date = get-date $file.LastWriteTime
if ($file_date -ge $date.AddDays(-$RotationDaily)) {
#Write-Host "$($file.Name) - $($file_date)"
Copy-Item "$LogDir\$file" "$LogDir\daily"
}
if ($file_date -ge $date.AddDays(-$RotationWeekly*7) -and [int]$file_date.DayOfWeek -eq $DayOfWeek) {
#Write-Host "Weekly $($file.Name) - $($file_date)"
Copy-Item "$LogDir\$file" "$LogDir\weekly"
}
if ($file_date -ge $date.AddDays(-$RotationMonthly*30) -and [int]$file_date.Day -eq $DayOfMonth) {
#Write-Host "Monthly $($file.Name) - $($file_date) $([int]$file_date.DayOfWeek)"
Copy-Item "$LogDir\$file" "$LogDir\monthly"
}
Remove-Item "$LogDir\$file"
}
$logs_daily = Get-ChildItem "$LogDir\daily" | where {$_.Attributes -ne "Directory"} | Sort-Object LastWriteTime -Descending
$logs_weekly = Get-ChildItem "$LogDir\weekly" | where {$_.Attributes -ne "Directory"}
$logs_monthly = Get-ChildItem "$LogDir\monthly" | where {$_.Attributes -ne "Directory"}
if ($logs_daily) {
foreach ($file in $logs_daily) {
$file_date = get-date $file.LastWriteTime
if ($file_date -le $date.AddDays(-$RotationDaily)) {
#Write-Host "$file.Name"
Remove-Item "$LogDir\daily\$file"
}
}
}
if ($logs_weekly) {
foreach ($file in $logs_weekly) {
$file_date = get-date $file.LastWriteTime
if ($file_date -le $date.AddDays(-$RotationWeekly*7)) {
#Write-Host "$file.Name"
Remove-Item "$LogDir\weekly\$file"
}
}
}
if ($logs_monthly) {
foreach ($file in $logs_monthly) {
$file_date = get-date $file.LastWriteTime
if ($file_date -le $date.AddDays(-$RotationMonthly*30)) {
#Write-Host "$file.Name"
Remove-Item "$LogDir\monthly\$file"
}
}
}
}
}
}
}
thanks for that script! but a licence comment would be nice 🙂
License noted. Public Domain no restrictions
thanks for the script, I tweaked it abit… added a regex filter and made it skip the log file made the day of the script running
https://gist.github.com/KingBain/b008f04d2f318a766162
Going to use this in unisen with the log_rotate_module apache module
Still a WIP might add some compression for the month old logs.
thanks again
John
Could you please answer why during log rotation files are being copied? Moving them is faster and this does not change file creation date.
Moving the file is a good thought. As is, you’re daily log could get copied to both the weekly and the monthly directory. Of course you could come up with some other logic to handle that allowing you to move the file and keep the original file date.
Saved me a bunch of time. Thanks!
I am a bit of a novice to Powershell, I can get the script working by running the following from within the folder the script is in:-
. .\GFS_Log_Rotation_function.ps1;rotate-logs -logdir E:\Reports
I am having real trouble getting this to work as a scheduled task though, can anyone explain to me how I can get this to work?
I worked it out, save the script as a .PSM1 then I created a .PS1 file with the information below, it worked a treat 😀
Import-Module C:\ocslms\Scripts\GFS_Log_Rotation_function.psm1
rotate-logs -logdir E:\Reports