Перейти к содержимому

Как найти и безопасно удалить старые .bak/.trn файлы бэкапов MSSQL с помощью PowerShell

Описание

Готовый PowerShell-скрипт для администраторов баз данных и системных администраторов Windows, который помогает держать диски с бэкапами MSSQL в порядке. Скрипт находит файлы резервных копий (.bak, .trn, .dif) старше заданного количества дней, выводит их в виде таблицы с путём, датой изменения и размером (отсортировано от самых больших к самым маленьким), сохраняет отчёт в CSV и, при необходимости, удаляет найденные файлы с записью в лог.

Возможности скрипта:

  • поиск бэкапов старше N дней на любом указанном диске или в папке;
  • вывод результатов с сортировкой по размеру файла;
  • сохранение отчёта в CSV для аудита перед удалением;
  • гибкий список папок-исключений — можно защитить от удаления любые важные каталоги с архивами;
  • переключаемый режим работы: только просмотр (безопасно, ничего не удаляется) или удаление — включается одной переменной $DeleteMode;
  • ведение лога всех удалённых файлов и возможных ошибок.

Скрипт не требует установки дополнительных модулей и запускается прямо в стандартной PowerShell-консоли Windows.

# ============================================================
# Поиск бэкапов MSSQL старше N дней на диске E:
# Один режим переключателем: только показать ИЛИ показать и удалить
# ============================================================

# --- Настройки ---
$DriveRoot     = 'E:\'
$DaysThreshold = 120
$Extensions    = @('*.bak', '*.trn', '*.dif')
$ReportPath    = "E:\MSSQL_Backups_Report_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv"
$LogFile       = "E:\Cleanup-OldMSSQLBackups.log"

# --- РЕЖИМ РАБОТЫ ---
# $false = только найти и показать (ничего не удалять)
# $true  = найти, показать И удалить
$DeleteMode = $false

# --- Папки-исключения (можно добавлять сколько угодно) ---
$ExcludeFolders = @(
    'E:\sql_backup\arhive base sql'
    # 'E:\ещё\одна\папка'
    # 'E:\и\ещё\одна'
)

# ============================================================
# Логика — дальше ничего менять не нужно
# ============================================================

$thresholdDate = (Get-Date).AddDays(-$DaysThreshold)
$normalizedExcludes = $ExcludeFolders | ForEach-Object { $_.TrimEnd('\').ToLower() }

Write-Host "Ищу бэкапы старше $DaysThreshold дней на $DriveRoot ..." -ForegroundColor Cyan
Write-Host "Режим: $(if ($DeleteMode) { 'УДАЛЕНИЕ' } else { 'ТОЛЬКО ПРОСМОТР' })" -ForegroundColor $(if ($DeleteMode) { 'Red' } else { 'Yellow' })
if ($normalizedExcludes.Count -gt 0) {
    Write-Host "Исключаю папки:" -ForegroundColor DarkGray
    $ExcludeFolders | ForEach-Object { Write-Host "  - $_" -ForegroundColor DarkGray }
}

# --- Единственный проход поиска ---
$allFiles = Get-ChildItem -Path $DriveRoot -Recurse -Force -ErrorAction SilentlyContinue -Include $Extensions |
    Where-Object { $_.LastWriteTime -lt $thresholdDate } |
    Where-Object {
        $filePathLower = $_.DirectoryName.ToLower()
        $isExcluded = $false
        foreach ($ex in $normalizedExcludes) {
            if ($filePathLower -eq $ex -or $filePathLower.StartsWith("$ex\")) {
                $isExcluded = $true
                break
            }
        }
        -not $isExcluded
    }

if ($allFiles.Count -eq 0) {
    Write-Host "Старых бэкапов не найдено (с учётом исключений)." -ForegroundColor Yellow
    return
}

# --- Формируем данные для вывода (один раз) ---
$backups = $allFiles | Select-Object FullName, LastWriteTime,
    @{Name='SizeMB'; Expression={[math]::Round($_.Length/1MB,2)}}

$sortedBackups = $backups | Sort-Object SizeMB -Descending

# --- Единственный вывод в консоль ---
$sortedBackups | Format-Table -AutoSize

$totalSizeMB = ($backups | Measure-Object -Property SizeMB -Sum).Sum
Write-Host "Найдено файлов: $($backups.Count), общий объём: $totalSizeMB MB" -ForegroundColor Green

# --- Сохраняем отчёт в CSV ---
$sortedBackups | Export-Csv -Path $ReportPath -NoTypeInformation -Encoding UTF8
Write-Host "Отчёт сохранён: $ReportPath" -ForegroundColor Green

# --- Удаление, если включён режим ---
if ($DeleteMode) {
    Write-Host "`nНачинаю удаление..." -ForegroundColor Red
    Add-Content -Path $LogFile -Value "----- Запуск удаления: $(Get-Date) -----"

    foreach ($file in $allFiles) {
        try {
            Remove-Item -Path $file.FullName -Force -ErrorAction Stop
            Add-Content -Path $LogFile -Value "УДАЛЁН: $($file.FullName) (дата: $($file.LastWriteTime))"
            Write-Host "Удалён: $($file.FullName)" -ForegroundColor DarkYellow
        } catch {
            Add-Content -Path $LogFile -Value "ОШИБКА при удалении $($file.FullName): $($_.Exception.Message)"
            Write-Host "Ошибка удаления: $($file.FullName)" -ForegroundColor Red
        }
    }

    Add-Content -Path $LogFile -Value "----- Удаление завершено: $(Get-Date) -----"
    Write-Host "`nУдаление завершено. Лог: $LogFile" -ForegroundColor Green
} else {
    Write-Host "`nРежим просмотра — файлы НЕ удалены." -ForegroundColor Cyan
    Write-Host "Чтобы удалить, поменяйте в начале скрипта: `$DeleteMode = `$true" -ForegroundColor Yellow
}

 

Similar Posts:

Добавить комментарий

Яндекс.Метрика