Guía completa para monitorizar el espacio en disco en vólumenes compartidos de Hyper-V con PowerShell

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.

Categorías:

Quizá también te interese…

×

¡Vean a NinjaOne en acción!

Al enviar este formulario, acepto la política de privacidad de NinjaOne.

Términos y condiciones de NinjaOne

Al hacer clic en el botón “Acepto” que aparece a continuación, estás aceptando los siguientes términos legales, así como nuestras Condiciones de uso:

  • Derechos de propiedad: NinjaOne posee y seguirá poseyendo todos los derechos, títulos e intereses sobre el script (incluidos los derechos de autor). NinjaOne concede al usuario una licencia limitada para utilizar el script de acuerdo con estos términos legales.
  • Limitación de uso: solo podrás utilizar el script para tus legítimos fines personales o comerciales internos, y no podrás compartirlo con terceros.
  • Prohibición de republicación: bajo ninguna circunstancia está permitido volver a publicar el script en ninguna biblioteca de scripts que pertenezca o esté bajo el control de cualquier otro proveedor de software.
  • Exclusión de garantía: el script se proporciona “tal cual” y “según disponibilidad”, sin garantía de ningún tipo. NinjaOne no promete ni garantiza que el script esté libre de defectos o que satisfaga las necesidades o expectativas específicas del usuario.
  • Asunción de riesgos: el uso que el usuario haga del script corre por su cuenta y riesgo. El usuario reconoce que existen ciertos riesgos inherentes al uso del script, y entiende y asume cada uno de esos riesgos.
  • Renuncia y exención: el usuario no hará responsable a NinjaOne de cualquier consecuencia adversa o no deseada que resulte del uso del script y renuncia a cualquier derecho o recurso legal o equitativo que pueda tener contra NinjaOne en relación con su uso del script.
  • CLUF: si el usuario es cliente de NinjaOne, su uso del script está sujeto al Contrato de Licencia para el Usuario Final (CLUF).