Some time ago I wrote a blog about monitoring SMART status with CrystalDiskInfo. After bringing this script over to our production RMM environment everything seemed good. But when I looked a little deeper I found that the script failed on NVME drives. NVME drives handle SMART-Status different from ‘regular’ SATA drives.
This started me on a quest for a solution that also worked on NVME drives. I’ve decided to use SmartMonTools as it has the same benefits as crystaldiskmark – It’s portable, does not require an installation, and is small enough to be downloaded on demand.
The script is fairly straightforward, it downloads the utility from a host, extracts the utility and runs an update for SmartCTL so it can fill in the data correctly. After this for each HDD in the system it will run a compare to the thresholds you’ve setup.
I’ve also had a request for disk monitoring on specifically the available spare count. The script can be edited to monitor this too – that way you can decide your own thresholds over what the manufacturer said is default for the disk.
The script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
############ Thresholds #############
$PowerOnTime = 35063 #about 4 years constant runtime.
$PowerCycles = 4000 #4000 times of turning drive on and off
$Temperature = 60 #60 degrees celcius
############ End Thresholds #########
$DownloadURL = "https://cyberdrain.com/wp-content/uploads/2020/02/Smartmontools.zip"
$DownloadLocation = "$($Env:ProgramData)\SmartmonTools"
try {
$TestDownloadLocation = Test-Path $DownloadLocation
if (!$TestDownloadLocation) { new-item $DownloadLocation -ItemType Directory -force }
$TestDownloadLocationZip = Test-Path "$DownloadLocation\Smartmontools.zip"
if (!$TestDownloadLocationZip) { Invoke-WebRequest -UseBasicParsing -Uri $DownloadURL -OutFile "$($DownloadLocation)\Smartmontools.zip" }
$TestDownloadLocationExe = Test-Path "$DownloadLocation\smartctl.exe"
if (!$TestDownloadLocationExe) { Expand-Archive "$($DownloadLocation)\Smartmontools.zip" -DestinationPath $DownloadLocation -Force }
}
catch {
write-host "The download and extraction of SMARTCTL failed. Error: $($_.Exception.Message)"
exit 1
}
#update the smartmontools database
start-process -filepath "$DownloadLocation\update-smart-drivedb.exe" -ArgumentList "/S" -Wait
#find all connected HDDs
$HDDs = (& "$DownloadLocation\smartctl.exe" --scan -j | ConvertFrom-Json).devices
$HDDInfo = foreach ($HDD in $HDDs) {
(& "$DownloadLocation\smartctl.exe" -t short -a -j $HDD.name) | convertfrom-json
}
$DiskHealth = @{}
#Checking SMART status
$SmartFailed = $HDDInfo | Where-Object { $_.Smart_Status.Passed -ne $true }
if ($SmartFailed) { $DiskHealth.add('SmartErrors',"Smart Failed for disks: $($SmartFailed.serial_number)") }
#checking Temp Status
$TempFailed = $HDDInfo | Where-Object { $_.temperature.current -ge $Temperature }
if ($TempFailed) { $DiskHealth.add('TempErrors',"Temperature failed for disks: $($TempFailed.serial_number)") }
#Checking Power Cycle Count status
$PCCFailed = $HDDInfo | Where-Object { $_.Power_Cycle_Count -ge $PowerCycles }
if ($PCCFailed ) { $DiskHealth.add('PCCErrors',"Power Cycle Count Failed for disks: $($PCCFailed.serial_number)") }
#Checking Power on Time Status
$POTFailed = $HDDInfo | Where-Object { $_.Power_on_time.hours -ge $PowerOnTime }
if ($POTFailed) { $DiskHealth.add('POTErrors',"Power on Time for disks failed : $($POTFailed.serial_number)") }
if (!$DiskHealth) { $DiskHealth = "Healthy" }
|
And that’s it! as always, Happy PowerShelling.