Windows Server Backup 2022: come impostare una retention di 14 giorni con PowerShell e Operazioni pianificate

Hai bisogno di mantenere 14 giorni di versioni con Windows Server Backup 2022, ma i backup tendono a sovrascriversi? In questa guida pratica ti mostro come ottenere una retention reale a 14 giorni con uno script PowerShell e due attività pianificate, senza acquistare nuovi strumenti.

Indice

Panoramica del problema

Steeve effettua backup giornalieri con Windows Server Backup (WSB) 2022. Usando una cartella di rete o un disco non dedicato, ha visto che i salvataggi si sovrascrivono e non ha trovato un’impostazione per conservare 14 copie. È un comportamento ricorrente quando:

  • la destinazione è una cartella di rete (share SMB) usata da un job pianificato;
  • si usa un disco non dedicato e WSB gestisce lo spazio cancellando autonomamente versioni più vecchie quando lo spazio si esaurisce;
  • si utilizza la modalità “una volta al giorno” verso la stessa destinazione, riusando il catalogo esistente.

Perché accade? Con share o dischi non dedicati WSB non offre un controllo puntuale del “numero di versioni da conservare”. Sui dischi dedicati, WSB mantiene più versioni finché c’è spazio; su share di rete e dischi non dedicati può riutilizzare il contenuto preesistente, e quando lo spazio scarseggia elimina i punti più vecchi.

Obiettivo della soluzione

Ottenere una retention certa di 14 giorni anche su share o dischi non dedicati, senza rinunciare a WSB. Lo faremo con due componenti:

  1. Script di backup: ogni esecuzione salva su una sottocartella distinta (timbrata con data/ora) quando la destinazione è una cartella di rete. In alternativa, su un disco locale non dedicato useremo WSB normalmente e affiancheremo un comando di “purge”.
  2. Script di pulizia: rimuove i backup più vecchi di 14 giorni (oppure mantiene solo gli ultimi N eseguiti).

Attenzione importante

  • Local path vs. network path: -backupTarget: accetta la radice di un volume locale (es. E:) oppure un percorso UNC di rete (es. \\filesrv\wsb$\). Non puoi indicare una sottocartella locale come C:\Backups\2025-10-25. La tecnica della cartella “con timestamp” si applica quindi alle condivisioni di rete (puoi usare \\filesrv\share\2025-10-25), non a percorsi locali.
  • Non destinare mai i backup alla stessa unità che stai proteggendo.
  • Esegui gli script e le attività con un account di servizio che abbia permessi di lettura/scrittura sulla share e privilegi amministrativi sul server.

Architettura della soluzione

Lo schema logico è semplice:

  1. Cartella base sulla share (es. \\filesrv01\CompanyBackups\SRV-APP01).
  2. Ogni giorno, lo script crea una sottocartella data-ora (es. 2025-10-25_230000) e avvia wbadmin verso quella sottocartella. WSB genererà al suo interno la struttura WindowsImageBackup<ComputerName>.
  3. Uno script di pulizia cancella le sottocartelle più vecchie di 14 giorni (o mantiene le ultime 14 esecuzioni).
  4. Operazioni pianificate avviano i due script secondo orari stabiliti.

Prerequisiti

  • Windows Server 2022 con Windows Server Backup installato (funzionalità “Backup di Windows Server”).
  • Una condivisione di rete con spazio adeguato (o un disco locale non dedicato separato dal sistema, es. E:).
  • Un account di servizio (dominio o locale) con: Log on as a batch job, diritti amministrativi sul server e accesso in scrittura alla share.

Script di backup

Versione per cartella di rete con sottocartella timbrata:

# Backup-Wsb-Network.ps1
param(
  [Parameter(Mandatory=$true)]
  [string]$ShareBase,                       # es: \\filesrv01\CompanyBackups\SRV-APP01
  [string[]]$IncludeVolumes = @("C:"),      # oppure vuoto e usare -AllCritical
  [switch]$AllCritical,
  [switch]$SystemState,
  [string]$LogPath = "C:\Logs\WSB"
)

--- Preparazione ---

$stamp = Get-Date -Format 'yyyy-MM-dd_HHmmss'
$targetPath = Join-Path -Path $ShareBase -ChildPath $stamp

New-Item -ItemType Directory -Path $targetPath -Force | Out-Null
New-Item -ItemType Directory -Path $LogPath -Force | Out-Null
$logFile = Join-Path $LogPath "Backup-$stamp.log"

Start-Transcript -Path $logFile -Append | Out-Null

try {
$args = @("start","backup","-backupTarget:`"$targetPath`"","-quiet")
if ($AllCritical) {
$args += "-allCritical"
} elseif ($IncludeVolumes.Count -gt 0) {
$args += "-include:" + ($IncludeVolumes -join ",")
}
if ($SystemState) { $args += "-systemState" }
Per evitare il truncate dei log applicativi (Exchange/SQL), valuta: $args += "-vssCopy"
```
Write-Host "Esecuzione: wbadmin $($args -join ' ')"
$p = Start-Process -FilePath "wbadmin.exe" -ArgumentList $args -Wait -NoNewWindow -PassThru
if ($p.ExitCode -ne 0) { throw "wbadmin ha restituito ExitCode $($p.ExitCode)" }
```
} catch {
Write-Error $_
exit 1
} finally {
Stop-Transcript | Out-Null
} 

Note operative:

  • Esegui l’attività pianificata come account di servizio con accesso alla share; in questo modo non servono parametri -user/-password nello script.
  • Se devi usare credenziali dedicate per la share, puoi registrarle in modo sicuro sul server con cmdkey /add:filesrv01 /user:DOMINIO\account /pass:.
  • Se fai più run al giorno, il timestamp con HHmmss evita collisioni.

Variante per disco locale non dedicato

Quando la destinazione è un volume locale (es. E:), WSB non accetta sottocartelle. Usa quindi un backup standard e affianca la pulizia per numero di versioni con wbadmin delete backup.

# Backup-Wsb-Local.ps1
param(
  [Parameter(Mandatory=$true)]
  [string]$TargetVolume,                    # es: E:
  [string[]]$IncludeVolumes = @("C:"),
  [switch]$AllCritical,
  [switch]$SystemState,
  [string]$LogPath = "C:\Logs\WSB"
)

$stamp = Get-Date -Format 'yyyy-MM-dd_HHmmss'
New-Item -ItemType Directory -Path $LogPath -Force | Out-Null
$logFile = Join-Path $LogPath "Backup-$stamp.log"
Start-Transcript -Path $logFile -Append | Out-Null

try {
$args = @("start","backup","-backupTarget:$TargetVolume","-quiet")
if ($AllCritical) { $args += "-allCritical" } elseif ($IncludeVolumes.Count -gt 0) { $args += "-include:" + ($IncludeVolumes -join ",") }
if ($SystemState) { $args += "-systemState" }
```
Write-Host "Esecuzione: wbadmin $($args -join ' ')"
$p = Start-Process -FilePath "wbadmin.exe" -ArgumentList $args -Wait -NoNewWindow -PassThru
if ($p.ExitCode -ne 0) { throw "wbadmin ha restituito ExitCode $($p.ExitCode)" }
```
} catch {
Write-Error $_
exit 1
} finally {
Stop-Transcript | Out-Null
} 

Script di pulizia (retention a 14 giorni)

Per share di rete con sottocartelle datate:

# Cleanup-Wsb-Network.ps1
param(
  [Parameter(Mandatory=$true)]
  [string]$ShareBase,          # es: \\filesrv01\CompanyBackups\SRV-APP01
  [int]$DaysToKeep = 14,
  [switch]$WhatIf
)

$cutoff = (Get-Date).AddDays(-$DaysToKeep)

Cancella solo cartelle che NON sono vuote e più vecchie della soglia

$oldFolders = Get-ChildItem -Directory $ShareBase -ErrorAction Stop |
Where-Object { $_.LastWriteTime -lt $cutoff }

foreach ($folder in $oldFolders) {
if ($WhatIf) {
Write-Host "[WhatIf] Eliminerei: $($folder.FullName)"
} else {
Write-Host "Elimino: $($folder.FullName)"
Remove-Item -LiteralPath $folder.FullName -Recurse -Force -ErrorAction Stop
}
} 

Se preferisci mantenere semplicemente le ultime 14 esecuzioni (indipendentemente dai giorni):

# Mantieni solo le ultime 14 cartelle per data di modifica
param(
  [Parameter(Mandatory=$true)]
  [string]$ShareBase,
  [int]$KeepLast = 14,
  [switch]$WhatIf
)

$ordered = Get-ChildItem -Directory $ShareBase | Sort-Object LastWriteTime -Descending
$toDelete = $ordered | Select-Object -Skip $KeepLast

foreach ($folder in $toDelete) {
if ($WhatIf) { Write-Host "[WhatIf] Eliminerei: $($folder.FullName)" }
else { Remove-Item -LiteralPath $folder.FullName -Recurse -Force }
} 

Per volume locale (nessuna sottocartella):

# Cleanup-Wsb-KeepVersions.ps1
param(
  [Parameter(Mandatory=$true)]
  [string]$TargetVolume = "E:",   # Volume destinazione del backup
  [int]$KeepVersions = 14
)

Rimuove le versioni oltre la quattordicesima

$cmd = "delete","backup","-backupTarget:$TargetVolume","-keepVersions:$KeepVersions","-quiet"
Write-Host "Esecuzione: wbadmin $($cmd -join ' ')"
Start-Process -FilePath "wbadmin.exe" -ArgumentList $cmd -Wait -NoNewWindow 

Pianificazione con Utilità di pianificazione (Task Scheduler)

Attività: backup giornaliero

  1. Apri Utilità di pianificazioneCrea attività….
  2. Scheda Generale:
    • Nome: WSB – Backup giornaliero
    • Esegui indipendentemente dalla connessione (se laptop) e Esegui con i privilegi più elevati.
    • Configura per: Windows Server 2022.
    • Account: l’account di servizio creato.
  3. Scheda Trigger: Nuovo → Ogni giorno, orario desiderato (es. 23:00).
  4. Scheda Azioni:
    • Programma/Script: powershell.exe
    • Aggiungi argomenti:
      • Per share: -NoProfile -ExecutionPolicy Bypass -File "C:\Scripts\Backup-Wsb-Network.ps1" -ShareBase "\\filesrv01\CompanyBackups\SRV-APP01" -AllCritical
      • Per volume locale: -NoProfile -ExecutionPolicy Bypass -File "C:\Scripts\Backup-Wsb-Local.ps1" -TargetVolume E: -AllCritical
    • Avvia in: C:\Scripts (cartella in cui risiedono gli script).
  5. Scheda Condizioni: deseleziona sospensione se server “always on”.
  6. Scheda Impostazioni: abilita “Esegui il task il prima possibile se viene mancata l’esecuzione pianificata”.

Attività: pulizia retention

  1. Crea una seconda attività: WSB – Retention 14 giorni.
  2. Trigger: giornaliero alle 05:00 (o settimanale se preferisci).
  3. Azioni:
    • Per share: powershell.exe -NoProfile -ExecutionPolicy Bypass -File "C:\Scripts\Cleanup-Wsb-Network.ps1" -ShareBase "\\filesrv01\CompanyBackups\SRV-APP01" -DaysToKeep 14
    • Per volume locale: powershell.exe -NoProfile -ExecutionPolicy Bypass -File "C:\Scripts\Cleanup-Wsb-KeepVersions.ps1" -TargetVolume E: -KeepVersions 14

Verifica dei risultati

  • Su share: controlla che in \\filesrv01\CompanyBackups\SRV-APP01 ci siano sottocartelle per ogni esecuzione (es. 2025-10-25_230000), ciascuna con WindowsImageBackup<Server>.
  • Su volume locale: verifica le versioni disponibili con: wbadmin get versions -backupTarget:E:
  • Controlla il Visualizzatore eventiApplicazioni e serviziMicrosoftWindowsBackupOperativo per conferme/suggerimenti di errore.
  • Esamina i log in C:\Logs\WSB creati dagli script (Transcript PowerShell).

Dimensionare la retention: quanta capacità serve?

WSB fa incrementali a livello blocco dopo il primo run. Come ordine di grandezza:

  • Primo giorno: full (dimensione prossima al totale dei dati selezionati).
  • Giorni successivi: solo blocchi cambiati. Il rapporto varia in base alla variazione quotidiana (per molti server applicativi 2–10%).

Per 14 giorni, una stima prudenziale è: Spazio ≈ 1×Full + 13×(Δ giornaliero). Esempio: full 500 GB e delta 5% (25 GB/giorno) → 500 + 13×25 = 825 GB. Aggiungi un margine 20–30% per sicurezza.

Note integrative utili (riassunto)

TemaDettagli pratici
Disco dedicatoSe inizializzi un disco dedicato con WSB, il tool mantiene automaticamente più versioni finché c’è spazio; non serve lo script di pulizia, ma non controlli il numero esatto di copie.
Comandi alternativiwbadmin delete backup -keepVersions:14 -backupTarget:<dest> -quiet rimuove le versioni oltre la quattordicesima. Inseriscilo in uno script e pianificalo, soprattutto quando la destinazione è un volume locale.
Altre opzioniPer retention avanzata (GFS, cifratura, test automatici, report), considera soluzioni terze come Azure Backup, Veeam, Hornet/Altaro, ecc., che includono motori di copia e purge nativi.
VSS Full vs Copy-vssFull può comportare il truncate dei log applicativi; se integri con altri backup applicativi, usa -vssCopy per non alterare lo stato dei log.
System StatePuoi aggiungere -systemState per proteggere AD, registry, driver, ecc. Valuta l’impatto di spazio/tempo e la frequenza (anche settimanale).
Compatibilità percorsiSui percorsi locali è richiesta la radice del volume (es. E:). Le sottocartelle sono supportate solo sui percorsi UNC (es. \\server\share\2025-10-25).
Fusi orari & localiEvita %date% dei file batch (dipende dal locale). In PowerShell usa Get-Date -Format 'yyyy-MM-dd_HHmmss' per nomi consistenti e ordinabili.

Troubleshooting rapido

  • Permessi share: errori di accesso → verifica NTFS e condivisione (lettura/scrittura) per l’account di servizio; se necessario registra credenziali con cmdkey.
  • Target non valido: “Sintassi del nome file o directory non corretta” → stai usando una sottocartella locale; passa a E: oppure usa una share UNC.
  • Spazio insufficiente: pianifica la pulizia prima del backup o aumenta la capacità. Verifica dimensioni con wbadmin get versions e occupazione della share.
  • Verifica riuscita: gli eventi 4xx nel log Microsoft-Windows-Backup/Operativo indicano esiti e dettagli di eventuali errori.

FAQ

Posso combinare copia giornaliera e full settimanale?
WSB non espone policy GFS. La combinazione più semplice è mantenere il job giornaliero e cambiare solo la retention (es. 14 giorni) con lo script di pulizia; per GFS nativo valuta un software di backup dedicato.

Faccio due backup al giorno: come regolo la retention?
Usa la variante “mantieni ultime N esecuzioni” (ad esempio 28 per due settimane × due run/dì) oppure mantieni per giorni ma con timestamp a minuti/secondi.

Come includo più volumi?
Passa -include:C:,D:,E: oppure usa -allCritical per proteggere i volumi necessari all’avvio e al ripristino bare-metal.

Come ripristino?
Apri WSB → Ripristina, indica il percorso della share e scegli data/ora. In alternativa usa wbadmin start recovery con i parametri opportuni.

Risultato

Implementando lo script di backup e lo script di pulizia più le due attività pianificate, Steeve ha confermato che i backup non si sovrascrivono più e che le copie più vecchie vengono eliminate automaticamente dopo 14 giorni. Il risultato è una retention stabile e verificabile con gli strumenti nativi di Windows Server Backup 2022, senza costi aggiuntivi.

Esempi di invocazione (pronti all’uso)

Backup su share con allCritical:

powershell.exe -NoProfile -ExecutionPolicy Bypass ^
  -File "C:\Scripts\Backup-Wsb-Network.ps1" ^
  -ShareBase "\\filesrv01\CompanyBackups\SRV-APP01" -AllCritical

Pulizia giornaliera > 14 giorni:

powershell.exe -NoProfile -ExecutionPolicy Bypass ^
  -File "C:\Scripts\Cleanup-Wsb-Network.ps1" ^
  -ShareBase "\\filesrv01\CompanyBackups\SRV-APP01" -DaysToKeep 14

Backup su volume E: e purge per versioni:

powershell.exe -NoProfile -ExecutionPolicy Bypass ^
  -File "C:\Scripts\Backup-Wsb-Local.ps1" -TargetVolume E: -AllCritical

powershell.exe -NoProfile -ExecutionPolicy Bypass ^
-File "C:\Scripts\Cleanup-Wsb-KeepVersions.ps1" -TargetVolume E: -KeepVersions 14 

Checklist finale

  • Script salvati in C:\Scripts e testati manualmente (PowerShell come amministratore).
  • Account di servizio con diritti adeguati e accesso alla share.
  • Due attività pianificate create, con Run with highest privileges e log attivo.
  • Cartella base su share: sottocartelle per data generate correttamente.
  • Pulizia: sottocartelle oltre 14 giorni rimosse.
  • Spazio: capacità pianificata con margine.

In sintesi: Windows Server Backup non espone un selettore “conserva N versioni” su share o dischi non dedicati. L’approccio combinato script di backup + script di pulizia + attività pianificate consente di raggiungere la retention a 14 giorni in modo affidabile e controllabile. Se un domani serviranno regole GFS, reporting e test di restore automatici, potrai migrare facilmente a una piattaforma di backup dedicata mantenendo lo stesso layout logico di destinazioni.

Con questa configurazione, la policy richiesta da Steeve è rispettata: i backup si susseguono senza sovrascriversi e i più vecchi vengono rimossi dopo 14 giorni.

Indice