简体   繁体   中英

Using Powershell to grab disk space info from remote servers and add to array

I've been trying to get some scripts together to automate some of the manual tasks that we still do reporting on. This one I'm trying to coax into connecting to each of the remote servers specified (I can AD link and filter it later), pull disk information, do a basic calculation, some formatting, and then stick it in an array to pull later.

I'm currently stuck with errors stating that I'm "attempting to divide by 0", and my array returns no data (I'm assuming because of the above". There has to be something small I'm missing. Well, hopefully small. Here's where I've gotten to:

#Variable listing servers to check. Can convert to a csv, or direct connection to AD 
   using OU's.
   $ServersToScan = @('x, y, z')

   #Blank Array for Report
   $finalReport = @()

   #Threshold Definition %
   $Critical = 5
   $Warning = 15

#Action for each server
foreach ($i in $ServersToScan)
{
Enter-PSSession -ComputerName $i

#Fixed Disk Info Gather
$diskObj = Get-CimInstance -ClassName Win32_LogicalDisk | Where-Object { $_.DriveType -eq 3 }

#Iterate each disk information - rewrite as foreach ($x in $diskObj) - rewritten 3/31/22
foreach ($diskObj in $diskObj)
    {
        # Calculate the free space percentage
        $percentFree = [int](($_.FreeSpace / $_.Size) * 100)

        # Determine the "Status"
        if ($percentFree -gt $Warning) {
            $Status = 'Normal'
        }
        elseif ($percentFree -gt $Critical) {
            $Status = 'Warning'
        }
        elseif ($percentFree -le $Critical) {
            $Status = 'Critical'
        }

        # Compose the properties of the object to add to the report
        $tempObj = [ordered]@{
            'Computer Name'    = $i
            'Drive Letter'     = $_.DeviceID
            'Drive Name'       = $_.VolumeName
            'Total Space (GB)' = [int]($_.Size / 1gb)
            'Free Space (GB)'  = [int]($_.FreeSpace / 1gb)
            'Free Space (%)'   = "{0}{1}" -f [int]$percentFree, '%'
            'Status'           = $Status
        }

        # Add the object to the final report
        $finalReport += New-Object psobject -property $tempObj
    }

Exit-PSSession
}

return $finalReport

Any insight would be great - thank you very much!!

There are 2 main problems, the first one, as Jeff Zeitlin pointed out, the automatic variable $_ ( $PSItem ) has no effect in a foreach loop, it is effectively $null :

[int](($null / $null) * 100)

# => RuntimeException: Attempted to divide by zero.

The second problem is your use of Enter-PSSession , which is used exclusively in interactive sessions . For an unattended script you would use Invoke-Command instead, however, in this case we could also rely on Get-CimInstance -ComputerName to query the remote computers ( note that this operation is performed in parallel and does not require a loop over the $serversToScan array ).

$ServersToScan = 'x, y, z'

#Threshold Definition %
$Critical = 0.5
$Warning = 0.15

$params = @{
    ClassName    = 'Win32_LogicalDisk'
    Filter       = "DriveType = '3'"
    ComputerName = $ServersToScan
}

$finalReport = Get-CimInstance @params | ForEach-Object {
    $free = $_.FreeSpace / $_.Size
    $status = switch($free) {
        { $_ -gt $Warning  } { 'Normal'; break }
        { $_ -gt $Critical } { 'Warning'; break }
        Default { 'Critical' }
    }
    
    [pscustomobject]@{
        'Computer Name'    = $_.PSComputerName
        'Drive Letter'     = $_.DeviceID
        'Drive Name'       = $_.VolumeName
        'Total Space (GB)' = $_.Size / 1Gb
        'Free Space (GB)'  = $_.FreeSpace / 1Gb
        'Free Space (%)'   = $free.ToString('P0')
        'Status'           = $status
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM