PowerShell for Storage and File System Management (Part 5)

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

Welcome back. In my previous article, I spent some time talking about the structure of a PowerShell function and I mentioned that we were going to create two functions. One of these functions is going to retrieve a disk’s SMART status and the other is going to perform a basic health check on a disk. By using both functions together, we should be able to get a pretty good idea of what is going on with our disks.

So with that said, I want to get started by building the function that examines each disk’s SMART status. Before I do, I just want to quickly mention that for right now my goal is to simply establish basic functionality. In other words, I want to build some working functions. These functions will probably evolve later on in the series, especially as I later incorporate them into a master script.

So as I said in the previous article, every function has to have a name. I’m going to call this function Get-Smart. If I were to keep things really simple, my Get-Smart function might look something like this:

Function Get-Smart

{

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

}

Such a function would definitely work, but there is one main problem with the function. It only runs against the local computer. As I mentioned in the previous article, our goal is to collect storage health data for multiple servers. So let’s take a look at how we might address this problem.

For the sake of demonstration, I have created a script called Smart.ps1. This script simply defines the function that I will be using to retrieve SMART status and then calls the function. The reason why I have created this script is to save myself a lot of typing since I am going to be repetedly modifying the code as we go along. So with that said, here is what my script looks like right now:

Function Get-Smart

{

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

}

Get-Smart

As you look at the script above, you will notice that my function has changed a little bit. There are two important changes that I have made. First, I added the –ComputerName parameter to my Get-WMIObject command. That way, I can run the command against a remote system. In this case, I am running the command against a server named Prod1.

The second change is that the command ends with a Select-Object command that is similar to what I showed you before, but that now displays the name of the system on which the disk resides. For example, if you look at Figure A, you can see that the disks reside on server Prod1.

Image
Figure A: The name of the remote server is now being displayed.

As you can see in the figure above, this function works really well. Before I move on and build onto what we have already accomplished, there are two important details that I need to mention.

First, the block of code that I am using only works because PowerShell remoting is enabled on all of my servers. If you need to enable PowerShell remoting on your servers, you can do so by using the Enable-PSRemoting cmdlet. There is a really good TechNet article that I recommend reading before you enable PowerShell remoting.

The other thing that I want to mention is that I didn’t have to provide any security credentials because all of my servers are domain members and I am logged in as a domain admin. If you need to provide a separate set of credentials then you can append the –Credential parameter to the Get-WMIObject cmdlet. You can find the syntax here.

So far we have retrieved SMART information from a remote server. However, we cheated a little bit by hard coding the name of the remote server into our script block. That would be fine if we only needed to query a single remote server, but remember that the ultimate goal is to check lots of servers. That being the case, we need to tweak the function a bit so that we can pass the server name to the function. Fortunately, this isn’t overly difficult to do. Here is how the script changes:

Function Get-Smart

{

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

}

“Prod1” | Get-Smart

As you can see in the code above, I have replaced the hard coded computer name with $Input. My function call has also changed. I am now specifying my target computer name (Prod1 in this case) just prior to calling the function. On the surface this might not seem any better because I am still using a hard coded server name, but this technique opens the door to querying multiple servers.

Querying multiple servers is relatively easy to do, but in order to do so, I have to introduce a bit of new code. Here is the script that gets the job done:

Function Get-Smart

{

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

}

 

$Servers = @(“Prod1”, “Prod2”)

ForEach ($Server in $Servers) {

$Server | Get-Smart

}

In the code above, the function hasn’t changed at all. It exists in exactly the same state as it did previously. It’s the function call that has changed.

Our function call now consists of four lines of code instead of one. The first of these lines is:

$Servers = @(“Prod1”, “Prod2”)

In this line, I am declaring a variable named $Servers. You will notice that there is an @ sign after the equals sign. This @ sign indicates that this variable is going to be an array. Because the variable is an array, I can populate it with multiple values. In this case those values are the server names. Each name is enclosed in quotation marks and separated by a comma.

The second line is:

ForEach ($Server in $Servers) {

We can’t just dump the entire contents of our array (multiple server names) into the function. If we do, the function will crash. Instead, we are using a ForEach statement to handle the array items (the server names) one at a time. We are introducing a new variable named $Server which will temporarily store the value of a single server as the script works through the list of servers.

The third and fourth lines of code are:

$Server | Get-Smart

}

These lines take what ever server name is stored in $Server at the moment and send that name to our function. Because we are using a ForEach loop, PowerShell will repeat this process for each server name. You can see the output of this function in Figure B.

Image
Figure B: We are using a script to send multiple server names to the Get-Smart function.

Conclusion

Now that I have shown you how to send multiple server names to our Get-Smart function, it’s time to create a function that retrieves basic disk health information from our servers. We will work on that in the next article. From there, we will filter the output so that less clutter is displayed and we will work to build a master script that we can run automatically.

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

About The Author

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