PowerShell for Storage and File System Management (Part 8)

If you would like to read the other parts in this article series please go to:

So far in this article series, I have shown you how to build a script that can analyze the health of the various physical disks in your servers. The script provides a lot of really useful information. It examines the SMART information (if available) for each disk, and also provides information on read errors, write errors, and temperature. This script just has one little problem. As it stands right now there is a huge potential for the script to spew a lot of data.

Let me show you what I mean. Here is my script as it exists right now:

Function Get-Smart

#Function to get disk SMART information

{

(Get-WmiObject -namespace root\wmi –class MSStorageDriver_FailurePredictStatus -ComputerName $Input | Select-Object PSComputerName, InstanceName, PredictFailure, Reason)

}

 

Function Get-Health

#Function to get disk health information

{

$Pdisk= Get-PhysicalDisk

ForEach ( $LDisk in $PDisk )

                {

                $LDisk.FriendlyName

                $LDisk.HealthStatus

                $LDisk | Get-StorageReliabilityCounter | Select-Object ReadErrorsTotal, WriteErrorsTotal, Temperature | FL

                Write-Host ==================

                }

}

 

#Script Body

$Servers = @(“Hyper-V-1”, “Hyper-V-2”, “Hyper-V-3”, “Hyper-V-4”, “Prod1”, “Prod2”)

                ForEach
($Server in $Servers) {

                $Server | Get-Smart

                Enter-PSSession -ComputerName $Server

                Get-Health

                Exit-PSSession

                }

The thing about this script that I really wanted to point out is this line:

$Servers = @(“Hyper-V-1”, “Hyper-V-2”, “Hyper-V-3”, “Hyper-V-4”, “Prod1”, “Prod2”)

This is the line of code that controls which servers will be analyzed. As you can see, I am going to be checking the storage health on six servers. Keep in mind that many organizations have far more servers than this. In fact, large organizations may have hundreds or even thousands of servers. With that in mind, take a look at the output from my script. As you can see in Figure A, I could not even fit all of the stats from the first server onto a single screen, much less the stats from my other servers.

Image

Figure A: This script produces a lot of information.

So what can we do about this? Well, the best option is probably going to be to apply some filters so that only information that is problematic is displayed. We can hide everything else so that the administrator’s attention is drawn to the items that really matter.

We can accomplish this by using the PowerShell Where-Object cmdlet. Before we do however, we need to set some threshold values. Let’s start with the disk temperature. What temperature would you consider to be problematic? Unfortunately (or fortunately, depending on how you look at it) I don’t have any disks that are seriously overheating. A quick scan of my disk temperatures reveals that the average disk temperature is about 35. With that in mind, I want to adapt this script to only display temperature data for disks whose temperature is above 35. Keep in mind that you will probably want to use a different value in your own script. I am simply doing this for demonstration purposes.

So with this goal in mind, here is a modified version of the script:

Function Get-Smart

#Function to get disk SMART information

{

(Get-WmiObject -namespace root\wmi –class MSStorageDriver_FailurePredictStatus -ComputerName $Input | Select-Object PSComputerName, InstanceName, PredictFailure, Reason)

}

 

Function Get-Health

#Function to get disk health information

{

$Pdisk= Get-PhysicalDisk

ForEach ( $LDisk in $PDisk )

                {

                $LDisk.FriendlyName

                $LDisk.HealthStatus

#             $LDisk | Get-StorageReliabilityCounter | Select-Object ReadErrorsTotal, WriteErrorsTotal, Temperature | FL

                $LDisk | Get-StorageReliabilityCounter | Where-Object {$_.Temperature -GT 35} | Select-Object Temperature | FL

                Write-Host ==================

                }

}

 

#Script Body

$Servers = @(“Hyper-V-1”, “Hyper-V-2”, “Hyper-V-3”, “Hyper-V-4”, “Prod1”, “Prod2”)

                ForEach ($Server in $Servers) {

                $Server | Get-Smart

                Enter-PSSession -ComputerName $Server

                Get-Health

                Exit-PSSession

                }

You can see the output from this modified script in Figure B.

Image
Figure B: This script only reports temperature data for disks with a temperature that is higher than 35 degrees.

So now that I have shown you the code and the script’s output, let’s take a look at what I have done. As you have probably noticed, I have made two modifications, as you can see here:

#             $LDisk | Get-StorageReliabilityCounter | Select-Object ReadErrorsTotal, WriteErrorsTotal, Temperature | FL

                $LDisk | Get-StorageReliabilityCounter | Where-Object {$_.Temperature -GT 35} | Select-Object Temperature | FL

The top line of code above is almost completely unchanged from above. I simply added a pound sign to the beginning of the line as a way of commenting out the line. In other words, PowerShell now sees this line as a comment rather than as code to be executed. The reason why I did this was because I wanted to keep my original code for reference purposes, but did not want the code getting in the way of what I was trying to do.

The second line of code is where things start to get interesting. The first portion of this line of code is identical to the line that I commented out. $LDisk is a variable representing the disk that is currently being analyzed. I am piping the disk name into the Get-StorageReliabilityCounter cmdlet so that I can view health and reliability data for the disk.

Originally I was outputting the total read errors, total write errors, and temperature for the disk. As you saw in Figure A though, that made for a long and tedious output. Instead of using the Select-Object cmdlet, I am now using the Where-Object cmdlet. By doing so, I am able to prevent the line of code from doing anything else unless a certain condition is met. In this case, the line of code does not display any data unless the disk temperature (represented by $_.Temperature) is greater than (-GT) 35 degrees.

If a disk does have a temperature in excess of 35 degrees then I want to know about it, and that’s where the last portion of this command comes into play. You will notice that the command ends with Select-Object Temperature | FL. This portion of the command only executes if the disk temperature is above 35 degrees and it will only display temperature data, nothing else. The data that is displayed is formatted as a list.

This raises a couple of questions. For starters, why am I telling PowerShell to Select-Object Temperature? Well, unless I explicitly state that I want to select the Temperature object, PowerShell will display a number of different health statistics for each disk that is overheating. In this particular case, I’m not interested in those other statistics. I only want to know about the disk temperature, so I am using the Select-Object Temperature cmdlet to filter out all of the other statistics.

The other question that this script brings to mind is what happens if a disk has read or write errors? As the script currently exists, those errors are being completely ignored. The reason for this is that I wanted to focus my attention on one specific data type rather than making the script more complicated by simultaneously examining multiple properties. I will eventually get to that however.

Conclusion

In this article, I began showing you how to filter the script based on temperature data. There are a couple of different things that I want to do before wrapping up this article. First, I want to finish revising the script to filter for other problematic conditions. The other thing that I want to do is to show you how to build a two stage filter. For example, if a disk’s temperature is over 35 degrees you may wish to include it in a report, but if a disk has a temperature of 45 degrees, you probably want to know about it now. I plan to show you how to generate an alert or to take corrective action for really high values.

If you would like to read the other parts in this article series please go to:

Leave a Comment

Your email address will not be published. Required fields are marked *

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Scroll to Top