Очередной пост про резервное копирование с философией много копий не бывает. На сей раз будем копать в сторону бэкапинга папки с самописными микроприложениями на веб-сервере.
На руках уютненький сервачок на ОС Ubuntu Server с gunicorn и массивом папок с микросервисными приложениями. Часть веб-приложений переданы пользователям для наполнения баз данных на SQLite. Тут никакой bigdata, никаких серверных СУБД. Всё скромно и со вкусом. Именно эту красоту и требуется бэкапить.
Всё, что нужно — собрать все папки с сервера и сложить на файловом хранилище. Ах, да! Нужно ещё и упаковать всё в архив, предусмотрев принцип хранения истории полного бэкапа.
Чтобы не изобретать колесо, сразу устанавливаем на сервер Samba и делаем папку с веб-приложениями доступной для чтения. Помнится, у меня уже был пост про общие папки в Linux. Только нужно заранее предусмотреть, что для нашей шары не нужны права на запись:
read only = yes
Теперь переходим к магии PowerShell:
# Пути к папкам #
$source = "\\192.168.1.100\apps"
$destination = "\\192.168.1.101\backup\webserver"
# Дней хранения #
$retentionDays = 120
# Создаем имя архива с текущей датой и временем #
$timestamp = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
$archiveName = "backup_$timestamp.zip"
$archivePath = Join-Path -Path $destination -ChildPath $archiveName
# Функция для удаления старых архивов #
function Remove-OldBackups {
param (
[string]$BackupPath,
[int]$DaysToKeep
)
$cutoffDate = (Get-Date).AddDays(-$DaysToKeep)
$oldArchives = Get-ChildItem -Path $BackupPath -Filter "backup_*.zip" |
Where-Object { $_.CreationTime -lt $cutoffDate }
foreach ($archive in $oldArchives) {
try {
Remove-Item -Path $archive.FullName -Force -ErrorAction Stop
Write-Host -ForegroundColor Green "Удален старый архив: $($archive.FullName)"
}
catch {
Write-Host -ForegroundColor Red "Ошибка при удалении архива $($archive.FullName): $_"
}
}
}
# Создаем архив #
try {
# Используем Compress-Archive для создания zip-архива #
Compress-Archive -Path "$source\*" -DestinationPath $archivePath -CompressionLevel Optimal
Write-Host -ForegroundColor Green "Архив успешно создан: $archivePath"
# Удаляем старые архивы #
Remove-OldBackups -BackupPath $destination -DaysToKeep $retentionDays
}
catch {
Write-Host -ForegroundColor Red "Ошибка при создании архива: $_"
# Логируем ошибку #
$errorMsg = "Ошибка при резервном копировании $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss'): $_"
$errorMsg | Out-File -FilePath "$destination\error_log.txt" -Append
}
Всего у скрипта три переменные: $source, $destination и $retentionDays. Первые две отвечают за папку-источник и папку-назначение, а вот третья переменная хранит в себе количество копий в днях. По умолчанию, копии старше 120 дней будут удалены с помощью функции Remove-OldBackups.
После того как все переменные заполнены — можно запускать скрипт. Логика работы кода такова: сначала формируется имя будущего архива, потом запускается сжатие файлов и в конце безжалостно удаляются старые архивы.
Имя созданного архива будет выглядеть примерно так backup_2026-08-21_14-30-45.zip.
В работе скрипта кроме никому не нужного вывода данных в консоль, предусмотрено журналирование ошибок в блоке catch.
В принципе, можно унифицировать скрипт, добавив параметры запуска для $source, $destination и $retentionDays. После этого вносить изменения в код не потребуется.