La gestión eficaz del espacio en disco es un aspecto fundamental para mantener una infraestructura informática eficiente y fiable. Una poderosa herramienta en el arsenal del profesional de TI es PowerShell, un marco de automatización de tareas de Microsoft. Hoy nos adentraremos en un script PowerShell diseñado para monitorizar el espacio en disco, en volúmenes compartidos en un entorno de cluster Hyper-V. Este script es especialmente valioso para los profesionales de TI y los proveedores de servicios gestionados (MSP) que necesitan garantizar que sus sistemas funcionan sin problemas y evitar tiempos de inactividad debidos a problemas de almacenamiento.
Antecedentes
Monitorizar el espacio en disco es crucial para evitar cortes inesperados y garantizar que las aplicaciones y los servicios funcionen sin interrupciones. Los volúmenes compartidos en un clúster Hyper-V pueden albergar numerosas máquinas virtuales, y quedarse sin espacio puede tener graves consecuencias. Este script de PowerShell simplifica el proceso de monitorizar el espacio en disco, permitiendo a los administradores vigilar el espacio libre y tomar medidas antes de que surjan problemas.
El script para monitorizar el espacio libre en disco
Requires -Version 5.1 <# .SYNOPSIS Hyper-V Monitor shared volume disk free space. Must be ran as a Local or Domain Admin user. .DESCRIPTION Hyper-V Monitor shared volume disk free space. Must be ran as a Local or Domain Admin user. .EXAMPLE (No Parameters) ## EXAMPLE OUTPUT WITHOUT PARAMS ## Name Path Size(GB) FreeSpace(GB) UsedSpace(GB) PercentFree ---- ---- -------- ------------- ------------- ----------- Cluster Virtual Disk (vd1) C:\ClusterStorage\vd1 3,068.98 168.77 2900.21 9.99 PARAMETER: -MinimumPercentage 20 Only errors when any shared volume disk is below the specified percentage. Defaults to 10 percent. .EXAMPLE -MinimumPercentage 20 ## EXAMPLE OUTPUT WITH MinimumPercentage ## Name Path Size(GB) FreeSpace(GB) UsedSpace(GB) PercentFree ---- ---- -------- ------------- ------------- ----------- Cluster Virtual Disk (vd1) C:\ClusterStorage\vd1 3,068.98 168.77 2900.21 9.99 PARAMETER: -MinimumFreeBytes 1073741824 Only errors when any shared volume disk is below the specified percentage. Defaults to 1GB or 1073741824 bytes. .EXAMPLE -MinimumFreeBytes 1073741824 ## EXAMPLE OUTPUT WITH MinimumFreeBytes ## Name Path Size(GB) FreeSpace(GB) UsedSpace(GB) PercentFree ---- ---- -------- ------------- ------------- ----------- Cluster Virtual Disk (vd1) C:\ClusterStorage\vd1 3,068.98 168.77 2900.21 9.99 PARAMETER: -ExcludeDrivesByName MyDisk Excludes drives that contains the text MyDisk in its name. .EXAMPLE -ExcludeDrivesByName 1073741824 ## EXAMPLE OUTPUT WITH ExcludeDrivesByName ## Name Path Size(GB) FreeSpace(GB) UsedSpace(GB) PercentFree ---- ---- -------- ------------- ------------- ----------- Cluster Virtual Disk (vd1) C:\ClusterStorage\vd1 3,068.98 168.77 2900.21 9.99 PARAMETER: -ExcludeDrivesByPath C:\ClusterStorage\MyDisk Excludes drives that contains the text MyDisk in its name. .EXAMPLE -ExcludeDrivesByPath C:\ClusterStorage\MyDisk .EXAMPLE -ExcludeDrivesByPath MyDisk ## EXAMPLE OUTPUT WITH ExcludeDrivesByPath ## Name Path Size(GB) FreeSpace(GB) UsedSpace(GB) PercentFree ---- ---- -------- ------------- ------------- ----------- Cluster Virtual Disk (vd1) C:\ClusterStorage\vd1 3,068.98 168.77 2900.21 9.99 PARAMETER: -CustomFieldParam "ReplaceMeWithAnyMultilineCustomField" Saves the results to a multi-line string custom field. .EXAMPLE -CustomFieldParam "ReplaceMeWithAnyMultilineCustomField" ## EXAMPLE OUTPUT WITH CustomFieldParam ## Name Path Size(GB) FreeSpace(GB) UsedSpace(GB) PercentFree ---- ---- -------- ------------- ------------- ----------- Cluster Virtual Disk (vd1) C:\ClusterStorage\vd1 3,068.98 168.77 2900.21 9.99 .OUTPUTS None .NOTES Minimum OS Architecture Supported: Windows Server 2016 Release Notes: Initial Release By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://www.ninjaone.com/terms-of-use. Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA). #> [CmdletBinding()] param ( [int]$MinimumPercentage = 10, $MinimumFreeBytes = 1GB, [String]$ExcludeDrivesByName, [String]$ExcludeDrivesByPath, [string]$CustomFieldParam ) begin { function Test-IsElevated { $id = [System.Security.Principal.WindowsIdentity]::GetCurrent() $p = New-Object System.Security.Principal.WindowsPrincipal($id) $p.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator) } function Test-IsSystem { $id = [System.Security.Principal.WindowsIdentity]::GetCurrent() return $id.Name -like "NT AUTHORITY*" -or $id.IsSystem } function Get-FriendlySize { param($Bytes) # Converts Bytes to the highest matching unit $Sizes = 'Bytes,KB,MB,GB,TB,PB,EB,ZB' -split ',' for ($i = 0; ($Bytes -ge 1kb) -and ($i -lt $Sizes.Count); $i++) { $Bytes /= 1kb } $N = 2 if ($i -eq 0) { $N = 0 } if ($Bytes) { "$([System.Math]::Round($Bytes,$N)) $($Sizes[$i])" }else { "0 B" } } function Get-Size { param ( [string]$String, [ValidateSet("PB", "TB", "GB", "MB", "KB", "B", "Bytes")][string]$DefaultSize = "GB" ) switch -wildcard ($String) { '*PB' { [int64]$($String -replace '[^\d+]+') * 1PB; break } '*TB' { [int64]$($String -replace '[^\d+]+') * 1TB; break } '*GB' { [int64]$($String -replace '[^\d+]+') * 1GB; break } '*MB' { [int64]$($String -replace '[^\d+]+') * 1MB; break } '*KB' { [int64]$($String -replace '[^\d+]+') * 1KB; break } '*B' { [int64]$($String -replace '[^\d+]+') * 1; break } '*Bytes' { [int64]$($String -replace '[^\d+]+') * 1; break } Default { Get-Size -String "$String $DefaultSize" } } } function Invoke-FilterDisks { [CmdletBinding()] param( [parameter(ValueFromPipeline = $true)] $Disks ) process { $Disks | ForEach-Object { # Check if exclude by name is needed if ($([string]::IsNullOrEmpty($ExcludeDrivesByName) -or [string]::IsNullOrWhiteSpace($ExcludeDrivesByName))) { $_ } else { if ( $_.Name -like "*$ExcludeDrivesByName*" ) { # Output Nothing } else { $_ } } } | ForEach-Object { # Check if exclude by name is needed if ($([string]::IsNullOrEmpty($ExcludeDrivesByPath) -or [string]::IsNullOrWhiteSpace($ExcludeDrivesByPath))) { $_ } else { if ( $_.Path -like "*$ExcludeDrivesByPath*" ) { # Output Nothing } else { $_ } } } } } if ($env:MinimumPercentage) { $MinimumPercentage = $env:MinimumPercentage } if ($env:minimumFreeSpace) { $MinimumFreeBytes = Get-Size -String $env:minimumFreeSpace } if ($env:ExcludeDrivesByName) { $ExcludeDrivesByName = $env:ExcludeDrivesByName } if ($env:ExcludeDrivesByPath) { $ExcludeDrivesByPath = $env:ExcludeDrivesByPath } if ($env:CustomFieldParam) { $CustomFieldParam = $env:CustomFieldParam } } process { if (Test-IsSystem) { Write-Error -Message "Access Denied. Please run with a Domain Account or a Local Account that has permissions to access this node." exit 1 } if (-not (Test-IsElevated)) { Write-Error -Message "Access Denied. Please run with Administrator privileges." exit 1 } Import-Module FailoverClusters -ErrorAction SilentlyContinue if (-not $(Get-Command -Name "Get-Cluster" -ErrorAction SilentlyContinue)) { Write-Error "[Error] Must run this script on a server that is apart of a Cluster or can communicate with a Cluster." exit 1 } try { Get-ClusterNode -ErrorAction Stop | Out-Null } catch { Write-Error "[Error] Failed to get Cluster Nodes." exit 1 } # Get Cluster Shared Volume Info $Volumes = foreach ( $csv in $(Get-ClusterSharedVolume) ) { foreach ( $csvinfo in $($csv | Select-Object -Property Name -ExpandProperty SharedVolumeInfo) ) { [PSCustomObject]@{ Name = $csv.Name Path = $csvinfo.FriendlyVolumeName Size = $csvinfo.Partition.Size FreeSpace = $csvinfo.Partition.FreeSpace UsedSpace = $csvinfo.Partition.UsedSpace PercentFree = $csvinfo.Partition.PercentFree } } } # Prep Format-Table substitutions $Size = @{ Label = "Size(GB)" ; Expression = { (Get-FriendlySize -Bytes $_.Size) } } $FreeSpace = @{ Label = "FreeSpace(GB)" ; Expression = { (Get-FriendlySize -Bytes $_.FreeSpace) } } $UsedSpace = @{ Label = "UsedSpace(GB)" ; Expression = { (Get-FriendlySize -Bytes $_.UsedSpace) } } $PercentFree = @{ Label = "PercentFree" ; Expression = { ($_.PercentFree) } } # Sort disks by FreeSpace $Disks = $Volumes | Sort-Object FreeSpace # Save results as a string $DisksFormattedString = $Disks | Format-Table -AutoSize Name, Path, $Size, $FreeSpace, $UsedSpace, $PercentFree | Out-String # If using a custom field sent that to the specified custom field, should be a multi-line if ($CustomFieldParam) { Ninja-Property-Set -Name $CustomFieldParam -Value $DisksFormattedString } # Loop through each disk $DiskUnderPercentage = $Disks | Invoke-FilterDisks | Where-Object { $_.PercentFree -lt $MinimumPercentage } $DiskUnderFreeBytes = $Disks | Invoke-FilterDisks | Where-Object { $_.FreeSpace -lt $MinimumFreeBytes } if ($DiskUnderPercentage -or $DiskUnderFreeBytes) { if ($DiskUnderPercentage) { Write-Host "[Issue] One or more Disks under $MinimumPercentage % free!" } if ($DiskUnderFreeBytes) { Write-Host "[Issue] One or more Disks under $(Get-FriendlySize -Bytes $MinimumFreeBytes) free!" } $DisksFormattedString | Write-Host exit 1 } # List all shared volumes if (-not $DiskUnderPercentage) { Write-Host "[Info] One or more Disks over $MinimumPercentage % free." } if (-not $DiskUnderFreeBytes) { Write-Host "[Info] One or more Disks over $(Get-FriendlySize -Bytes $MinimumFreeBytes) free." } $DisksFormattedString | Write-Host exit 0 } end { }
Análisis detallado
Vamos a desglosar el script paso a paso para entender su funcionalidad y cómo puede utilizarse eficazmente para monitorizar el espacio en disco.
1. Requisitos previos y configuración inicial. El script para monitorizar el espacio en disco requiere PowerShell versión 5.1 y debe ejecutarse con privilegios administrativos. Comienza definiendo varios parámetros como MinimumPercentage, MinimumFreeBytes, ExcludeDrivesByName, ExcludeDrivesByPath y CustomFieldParam.
2. Funciones de comprobación de privilegios y cálculo de tamaños
- Test-IsElevated comprueba si el script se está ejecutando con privilegios de administrador.
- Test-IsSystem asegura que el script no se está ejecutando como una cuenta del sistema.
- Get-FriendlySize y Get-Size convierten los valores en bytes a unidades más legibles como KB, MB, GB, etc.
3. Filtrado y variables de entorno. El script para monitorizar el espacio en disco configura funciones para filtrar unidades en función de nombres o rutas especificados. También comprueba si existen variables de entorno que puedan anular los parámetros del script.
4. Recuperación de información sobre clústeres y volúmenes. El script para monitorizar el espacio en disco importa el módulo FailoverClusters y verifica que se está ejecutando en un servidor que forma parte de un cluster. A continuación, recupera información sobre los volúmenes compartidos en el clúster, incluyendo su tamaño, espacio libre, espacio utilizado y porcentaje de espacio libre.
5. Formateo y salida. El script para monitorizar el espacio en disco formatea la información del disco para que sea legible y comprueba si algún volumen está por debajo de los umbrales de espacio libre especificados. Si se detectan problemas, muestra los detalles y sale con un estado de error. En caso contrario, confirma que todos los volúmenes tienen suficiente espacio libre.
Posibles casos de uso
Imagina un administrador de TI responsable de un clúster Hyper-V que aloja máquinas virtuales críticas. Este administrador puede utilizar el script para automatizar la monitorización del espacio en disco, asegurándose de que se le avisa antes de que cualquier volumen se quede críticamente corto de espacio. Este enfoque proactivo les permite asignar almacenamiento adicional o limpiar archivos innecesarios, evitando posibles cortes y manteniendo el rendimiento del sistema.
Comparaciones
En comparación con la supervisión manual o el uso de herramientas básicas integradas, este script para monitorizar el espacio en disco proporciona un enfoque más automatizado y detallado. No sólo comprueba el espacio libre, sino que también permite la personalización basada en nombres de volúmenes, rutas y requisitos específicos de espacio libre. Otros métodos, como las herramientas de supervisión de terceros, pueden ofrecer una funcionalidad similar, pero a menudo tienen un coste más elevado y requieren una configuración adicional.
FAQ
P: ¿Este script para monitorizar el espacio en disco puede ejecutarse en cualquier versión de Windows Server?
R: El script para monitorizar el espacio en disco es compatible con Windows Server 2016 y versiones posteriores debido a los requisitos del módulo FailoverClusters.
P: ¿Qué permisos se necesitan para ejecutar este script?
R: El script para monitorizar el espacio en disco debe ejecutarse con privilegios de administrador local o de dominio para acceder a la información necesaria del clúster.
P: ¿Cómo puedo excluir determinados volúmenes de la supervisión?
R: Puedes utilizar los parámetros ExcludeDrivesByName o ExcludeDrivesByPath para filtrar volúmenes específicos en función de sus nombres o rutas.
Implicaciones
Los resultados de este script para monitorizar el espacio en disco pueden afectar significativamente a las operaciones de TI. Al identificar los volúmenes con insuficiente espacio libre, los administradores pueden tomar medidas preventivas para evitar interrupciones del servicio. Esta supervisión proactiva también mejora la fiabilidad y el rendimiento general del sistema, contribuyendo a un entorno informático más estable.
Recomendaciones
Cuando utilices este script para monitorizar el espacio en disco, ten en cuenta las siguientes prácticas recomendadas:
- Programa el script para que se ejecute a intervalos regulares mediante el Programador de tareas o herramientas similares.
- Personaliza los parámetros en función de las necesidades específicas de tu entorno.
- Asegúrate de que dispones de permisos suficientes y de que ejecutas el script en los servidores adecuados.
Reflexiones finales
Los scripts de PowerShell como éste para monitorizar el espacio en disco son herramientas inestimables para los profesionales de TI y los MSP, ya que ofrecen potentes funciones de automatización para gestionar y supervisar sistemas críticos. Al incorporar estos scripts a sus flujos de trabajo, los administradores pueden mantener un mejor control sobre su infraestructura, garantizar un rendimiento óptimo y prevenir posibles problemas antes de que se agraven.
NinjaOne, el software líder en operaciones de TI, puede mejorar aún más este proceso mediante la integración de la ejecución de scripts con sus capacidades de supervisión y gestión, proporcionando una solución integral para la gestión de la infraestructura de TI.