PowerShell · 21.08.2026

Микросервисный бэкап

Очередной пост про резервное копирование с философией много копий не бывает. На сей раз будем копать в сторону бэкапинга папки с самописными микроприложениями на веб-сервере.

На руках уютненький сервачок на ОС 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. После этого вносить изменения в код не потребуется.