Quando il disco si riempie, il problema raramente è “solo” spazio: saltano servizi, si corrompono code, falliscono backup e i tempi di risposta diventano imprevedibili. Su Windows Server la soluzione sensata non è guardare ogni tanto Esplora file, ma avere un controllo automatico, leggibile e abbastanza semplice da non rompersi alla prima modifica. Uno script PowerShell ben fatto per monitorare lo spazio disco serve proprio a questo: intercetta il trend prima dell’emergenza, produce segnali utili e lascia traccia di ciò che è successo.
Il punto non è scrivere “uno script che fa un Get-PSDrive”. Quello è il minimo sindacale. Il punto è decidere cosa misurare, come interpretarlo e come reagire senza trasformare il controllo in un altro punto di guasto. In pratica: soglie chiare, output comprensibile, log persistente, exit code coerenti e un modo semplice per integrarlo con Utilità di pianificazione, monitoraggio centralizzato o un sistema di alert già esistente.
Che cosa deve fare davvero uno script di monitoraggio disco
Un buon script non deve limitarsi a dire se un volume è sotto una certa percentuale. Deve distinguere tra controllo operativo e segnale utile. In un ambiente reale, per esempio, un volume al 78% può essere normale se cresce lentamente e viene bonificato ogni settimana; lo stesso valore diventa critico se il trend indica esaurimento in 36 ore. Per questo conviene raccogliere almeno tre elementi: spazio totale, spazio libero e percentuale di utilizzo. Se vuoi fare un passo in più, aggiungi il trend basato su più misurazioni consecutive o su un file di storico.
In più, va deciso il perimetro. Monitori tutti i volumi locali? Escludi le unità rimovibili? Tratti separatamente i mount point? Su server con storage applicativo, database o cartelle di log molto attive, la distinzione tra lettera di unità e mount point è importante. Lo script deve essere esplicito: niente assunzioni vaghe, perché l’ambiguità è il modo più rapido per avere falsi positivi o buchi di copertura.
Approccio pratico: soglie, log e uscita del processo
La struttura più robusta resta quella a livelli. Ad esempio:
- OK: uso inferiore alla soglia di attenzione.
- WARN: superata una soglia intermedia, serve verifica umana.
- CRIT: spazio insufficiente per operare con margine, serve intervento.
La soglia non va scelta a caso. Per molti ambienti Windows Server una coppia ragionevole è 80%/90%, ma la cifra va adattata al carico: su volumi che ospitano database, file temporanei o code, il margine utile può essere più alto o più basso. Se il volume cresce in modo prevedibile, conta più il tempo residuo stimato che la percentuale secca. Se invece il carico è bursty, la percentuale rimane la metrica più semplice da automatizzare.
Per il logging, evita il classico output “a video” e basta. Un log testuale con timestamp, nome host, lettera di unità, spazio libero in GB e percentuale è sufficiente nella maggior parte dei casi. Se il contesto è più strutturato, valuta CSV o JSON. Il punto è rendere il dato riutilizzabile da SIEM, task scheduler, pipeline di monitoraggio o semplice analisi manuale.
Script PowerShell base, ma già usabile in produzione
Qui sotto c’è una base concreta. Non è un giocattolo da laboratorio: gestisce soglie, produce output leggibile e restituisce un exit code diverso in base allo stato. È il minimo per farlo girare in pianificazione o agganciarlo a un sistema esterno.
param(
[int]$WarnThreshold = 80,
[int]$CritThreshold = 90,
[string]$LogPath = "C:\ProgramData\RunningLow\disk-monitor.log"
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$hostname = $env:COMPUTERNAME
$issues = @()
$volumes = Get-CimInstance Win32_LogicalDisk -Filter "DriveType=3"
foreach ($vol in $volumes) {
if ($null -eq $vol.Size -or $vol.Size -eq 0) {
continue
}
$freeGB = [math]::Round($vol.FreeSpace / 1GB, 2)
$totalGB = [math]::Round($vol.Size / 1GB, 2)
$usedPct = [math]::Round((1 - ($vol.FreeSpace / $vol.Size)) * 100, 2)
$line = "[$timestamp] $hostname $($vol.DeviceID) Free=${freeGB}GB Total=${totalGB}GB Used=${usedPct}%"
Add-Content -Path $LogPath -Value $line
if ($usedPct -ge $CritThreshold) {
$issues += "CRIT $($vol.DeviceID) $usedPct%"
}
elseif ($usedPct -ge $WarnThreshold) {
$issues += "WARN $($vol.DeviceID) $usedPct%"
}
}
if ($issues.Count -gt 0) {
$issues | ForEach-Object { Write-Output $_ }
if ($issues -match '^CRIT') {
exit 2
}
exit 1
}
Write-Output "OK"
exit 0
La scelta di Win32_LogicalDisk è pratica perché funziona bene sui volumi locali. In alternativa puoi usare Get-PSDrive, ma in ambienti server è meno preciso per distinguere ciò che è davvero un disco locale da provider PowerShell o percorsi non interessanti. Se il requisito è solo “quanto spazio libero ho su C:”, la classe CIM è più pulita.
Il codice sopra usa una logica semplice: se trova almeno un volume sopra la soglia di warning, esce con 1; se trova un critico, esce con 2; altrimenti 0. Questo schema è comodo perché consente a un job schedulato, a un orchestratore o a un sistema di alert di distinguere tra attenzione e incidente. Se il tuo stack pretende un formato diverso, il mapping si adatta senza riscrivere tutto.
Versione con report più leggibile e storico locale
Se vuoi qualcosa di più utile nella pratica, aggiungi un report CSV o JSON. Il file di log lineare è ottimo per il troubleshooting rapido, ma un report strutturato permette di fare trend, grafici o confronti giornalieri senza parsing fragile. Un esempio semplice è salvare ogni esecuzione in un CSV con data, host, drive, totale, libero e percentuale.
$reportPath = "C:\ProgramData\RunningLow\disk-report.csv"
$rows = foreach ($vol in $volumes) {
if ($null -eq $vol.Size -or $vol.Size -eq 0) { continue }
[pscustomobject]@{
Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
Hostname = $hostname
Drive = $vol.DeviceID
FreeGB = [math]::Round($vol.FreeSpace / 1GB, 2)
TotalGB = [math]::Round($vol.Size / 1GB, 2)
UsedPct = [math]::Round((1 - ($vol.FreeSpace / $vol.Size)) * 100, 2)
}
}
$rows | Export-Csv -Path $reportPath -NoTypeInformation -Append
Il vantaggio del CSV è banale ma decisivo: quando il problema arriva, non devi ricostruire i dati a mano. Puoi aprire il file, filtrare per drive, confrontare date e capire se il riempimento è stato improvviso o graduale. Se lavori in ambienti con più server, il formato strutturato ti permette anche di centralizzare i risultati con un semplice job di raccolta.
Esecuzione pianificata con Utilità di pianificazione
Su Windows, il modo più pulito per farlo girare in modo affidabile è una scheduled task. È preferibile a un processo lasciato in background, perché il task scheduler fornisce retry, storico esecuzioni e controllo del contesto utente. Per uno script di monitoraggio disco, di solito conviene eseguirlo con un account di servizio con privilegi minimi necessari a leggere i volumi e scrivere nella cartella di log.
Creare il task da GUI riduce errori di sintassi, ma in ambienti amministrati la versione PowerShell è più ripetibile. Un esempio essenziale:
$action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File C:\Scripts\RunningLow.ps1"
$trigger = New-ScheduledTaskTrigger -Daily -At 08:00
$principal = New-ScheduledTaskPrincipal -UserId "DOMAIN\svc-monitor" -LogonType Password -RunLevel LeastPrivilege
Register-ScheduledTask -TaskName "RunningLow Disk Monitor" -Action $action -Trigger $trigger -Principal $principal
Qui c’è un dettaglio da non sottovalutare: ExecutionPolicy Bypass nel task non è una scorciatoia universale, è una scelta operativa. Se la tua policy aziendale lo vieta, firma lo script oppure abilita l’esecuzione in modo coerente con il modello di sicurezza del server. In ogni caso, il task deve essere tracciabile: nome chiaro, account chiaro, percorso script fisso e log in una directory protetta.
Alert: email, evento applicativo o integrazione con un sistema esterno
Il monitoraggio serve solo se qualcuno riceve il segnale giusto. L’invio email diretto da PowerShell è ancora comune, ma in molti ambienti è meglio scrivere nel log applicativo, generare un evento Windows o inviare un webhook verso il sistema di alerting già in uso. Il motivo è semplice: meno dipendenze locali, meno rischio di blocchi dovuti a SMTP, TLS o autenticazione.
Se devi proprio spedire una mail, non mettere mai credenziali in chiaro nello script. Usa un secret vault, un account dedicato o un meccanismo gestito dal server. E soprattutto fai in modo che l’invio sia secondario rispetto al controllo: se la mail fallisce, il monitoraggio non deve perdere il dato. Prima scrivi il log, poi provi l’alert.
Per l’evento Windows, una soluzione sobria è registrare un source dedicato e scrivere nel registro applicazioni. Così il SOC, il sistema di monitoraggio o un semplice filtro Event Viewer possono agganciare il segnale senza leggere file custom. È una scelta molto più robusta di un file in una cartella temporanea che viene ripulita da una maintenance task.
Gestione dei falsi positivi e dei casi sporchi
Il vero lavoro in questi script è ridurre rumore. Ci sono volumi quasi pieni che non sono un problema immediato, perché ospitano dati statici e hanno una procedura di espansione già pronta. Ci sono invece volumi apparentemente sani che diventano critici in poche ore, perché contengono log, spool, cache o file temporanei. Per questo conviene classificare i volumi, almeno logicamente, in base al ruolo.
- Volumi applicativi: soglie più strette, alert immediato.
- Volumi di log: soglia più conservativa, trend più importante della percentuale istantanea.
- Volumi statici: controllo meno frequente, ma sempre presente.
Se hai mount point invece di lettere di unità, conviene mappare il ruolo nel nome del path o in un file di configurazione esterno. Lo script non deve sapere a memoria il significato di D: o E:; deve leggere una configurazione e agire di conseguenza. È una piccola differenza che riduce gli errori quando cambiano i server o i team.
Estensione utile: soglia basata sul trend
La percentuale istantanea ti dice dove sei, il trend ti dice dove stai andando. Se salvi i risultati nel tempo, puoi aggiungere una stima molto semplice: quanto spazio libero perdi in media al giorno. Anche un calcolo grezzo è spesso sufficiente per capire se hai 10 giorni di margine o 10 ore. Non serve un modello predittivo complicato per ottenere valore operativo.
Un approccio minimale consiste nel confrontare l’ultimo valore con quello di 24 ore prima, oppure con la media degli ultimi N campioni. Se il delta supera una soglia, lo script può alzare la severità anche quando la percentuale non è ancora alta. In ambienti con backup temporanei, export massivi o elaborazioni batch, questa logica evita di arrivare tardi.
Hardening minimo: permessi, path e manutenzione
Lo script deve vivere in una directory stabile, per esempio C:\Scripts\RunningLow\, con permessi limitati. Il log dovrebbe stare in C:\ProgramData\RunningLow\ o in un percorso equivalente protetto. Evita di scrivere in cartelle utente o desktop: sono percorsi fragili, spesso soggetti a pulizia, profili temporanei o policy di redirezione.
Se lo script viene distribuito su più server, tieni il file sotto controllo versione. Anche una versione semplice in repository interno è sufficiente: sai chi ha cambiato cosa, puoi fare diff e rientrare rapidamente se una modifica introduce rumore o rompe l’output. In un contesto operativo, la tracciabilità vale più di qualche riga in meno.
Infine, documenta tre cose: soglie usate, frequenza di esecuzione e comportamento in caso di errore. Se il log non è scrivibile, lo script deve dirlo chiaramente; se un volume non è interrogabile, deve segnalarlo; se il task fallisce, il fallimento deve essere visibile. Il monitoraggio che fallisce in silenzio è peggio di nessun monitoraggio.
Checklist operativa prima di metterlo in produzione
- Definisci le soglie per ambiente, non una soglia unica per tutti i server.
- Decidi il formato di output: log testuale, CSV o entrambi.
- Verifica che l’account del task abbia accesso in lettura ai volumi e in scrittura al log.
- Controlla che il percorso script sia stabile e versionato.
- Prova il comportamento con un volume quasi pieno e uno sano.
- Simula un errore di permesso sul file di log per vedere se l’errore emerge chiaramente.
- Integra l’uscita con il sistema di alerting che usi davvero, non con un canale provvisorio.
Se segui questa linea, lo script PowerShell per monitorare lo spazio disco smette di essere un esercizio di sintassi e diventa un controllo operativo serio. La differenza la fanno i dettagli: uscita coerente, log utile, soglie sensate e un’integrazione che non dipende dal caso.
Commenti (0)
Nessun commento ancora.
Segnala contenuto
Elimina commento
Eliminare definitivamente questo commento?
L'azione non si può annullare.