Advertisement
nullzilla

Monitor - Drive SMART Values

Aug 31st, 2021 (edited)
1,407
2
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. Import-Module $env:SyncroModule -DisableNameChecking
  2. #Requires -Version 3.0
  3.  
  4. <# Version 1.1
  5. .DESCRIPTION
  6. Obtain and evaluate SMART data from drives and alert based on ID value thresholds.
  7. Uses WMI so no outside tools are needed but ome hardware/configuration may not be compatible.
  8.  
  9. The threshold values used below are guesstimates as to what might be concerning. Sometimes
  10. manufacturers use the same attribute number for different purposes, calculate things differently,
  11. or use Worst vs RawValue. If you come across these exceptions, please report them or do a pull request
  12. so the script can improve.  Don't take any one value as critical and adjust as you feel appropreiate for
  13. your environment and risk level, or even remove attributes from monitoring entirely.
  14.  
  15. .NOTES
  16. Created by Isaac Good with data processing function from https://github.com/Fantastitech/GetSmartWin/blob/master/getsmartwin.ps1
  17.     v1.0 - 2018-11-05
  18.     v1.1 - 2022-02-25
  19.         Added - description, changlog and comments
  20.         Added - if statements for SSD and spinner specific IDs
  21.         Changed - split out ID 233 for Intel (and maybe others?) as they use Worst value instead of RawValue
  22. #>
  23.  
  24. # If this is a virtual machine, we don't need to continue
  25. $Computer = Get-CimInstance -ClassName 'Win32_ComputerSystem'
  26. if ($Computer.Model -like 'Virtual*') {
  27.     exit
  28. }
  29.  
  30. # Clear our variable so we have good output when testing
  31. $Warnings = @()
  32.  
  33. # Grab the instance names for disks that have WMI SMART data available
  34. # This is where the "Not supported" error can be generated from, which we check for later
  35. $disks = (Get-CimInstance -Namespace 'Root\WMI' -ClassName 'MSStorageDriver_FailurePredictStatus' | Select-Object 'InstanceName').InstanceName
  36.  
  37. foreach ($disk in $disks) {
  38.     # Since MSStorageDriver_FailurePredictStatus and Get-PhysicalDisk don't share any values to
  39.     # uniquely identify a disk so we can check if SSD, we have to go through an intermediate step
  40.     # of getting the serial number to match against. Maybe there's a better way that I'm missing. #>
  41.    
  42.     # Strip instance name down to a value we can match against
  43.     $product = [regex]::Matches($disk,"(?<=Prod_).*(?=\\)").Value
  44.  
  45.     # Grab the serial for the disk that matches the instance name
  46.     $serial = (Get-CimInstance -ClassName Win32_DiskDrive | Where-Object { $_.PNPDeviceID -match "$product"}).SerialNumber
  47.    
  48.     # Use the serial to check if the disk is an SSD
  49.     $ssd = Get-PhysicalDisk | Where-Object { $_.SerialNumber -eq $serial } | Where-Object -Property MediaType -eq SSD
  50.  
  51.     # Retrieve SMART data
  52.     $SmartData = (Get-CimInstance -Namespace 'Root\WMI' -ClassName 'MSStorageDriver_ATAPISMartData' | Where-Object 'InstanceName' -eq $disk)
  53.     [Byte[]]$RawSmartData = $SmartData | Select-Object -ExpandProperty 'VendorSpecific'
  54.    
  55.     # Starting at the third number (first two are irrelevant)
  56.     # get the relevant data by iterating over every 12th number
  57.     # and saving the values from an offset of the SMART attribute ID
  58.     [PSCustomObject[]]$Output = for ($i = 2; $i -lt $RawSmartData.Count; $i++) {
  59.         if (0 -eq ($i - 2) % 12 -and $RawSmartData[$i] -ne 0) {
  60.             # Construct the raw attribute value by combining the two bytes that make it up
  61.             [Decimal]$RawValue = ($RawSmartData[$i + 6] * [Math]::Pow(2, 8) + $RawSmartData[$i + 5])
  62.             $InnerOutput = [PSCustomObject]@{
  63.                 DiskID   = $disk
  64.                 ID       = $RawSmartData[$i]
  65.                 #Flags    = $RawSmartData[$i + 1]
  66.                 #Value    = $RawSmartData[$i + 3]
  67.                 Worst    = $RawSmartData[$i + 4]
  68.                 RawValue = $RawValue
  69.             }
  70.             $InnerOutput
  71.         }
  72.     }
  73.  
  74.     # Display table of values
  75.     $Output | Sort-Object ID | Out-String
  76.  
  77.     # Spinner-specific ID's
  78.     if (-not $ssd) {
  79.         # Spin Retry Count
  80.         $Warnings += $Output | Where-Object ID -eq 10 | Where-Object RawValue -ne 0 | Format-Table
  81.  
  82.         # Recalibration Retries
  83.         $Warnings += $Output | Where-Object ID -eq 11 | Where-Object RawValue -ne 0 | Format-Table
  84.  
  85.         # High Fly Writes
  86.         $Warnings += $Output | Where-Object ID -eq 189 | Where-Object RawValue -ne 0 | Format-Table
  87.     }
  88.  
  89.     # Reallocated Sectors Count / Retired NAND Blocks
  90.     $Warnings += $Output | Where-Object ID -eq 5 | Where-Object RawValue -gt 1 | Format-Table
  91.  
  92.     # Spare Blocks Available
  93.     $Warnings += $Output | Where-Object ID -eq 16 | Where-Object RawValue -lt 100 | Format-Table
  94.  
  95.     # Remaining Spare Blocks
  96.     $Warnings += $Output | Where-Object ID -eq 17 | Where-Object RawValue -lt 100 | Format-Table
  97.  
  98.     # Unexpected Power Loss Count (Unsafe Shutdowns Count on PCIe SSDs)
  99.     $Warnings += $Output | Where-Object ID -eq 174 | Where-Object RawValue -gt 300 | Format-Table
  100.  
  101.     # Used Reserved Block Count Total
  102.     $Warnings += $Output | Where-Object ID -eq 178 | Where-Object RawValue -gt 1 | Format-Table
  103.  
  104.     # Used Reserved Block Count Total
  105.     $Warnings += $Output | Where-Object ID -eq 179 | Where-Object RawValue -gt 1 | Format-Table
  106.  
  107.     # Unused Reserved Block Count or Percentage Remaining (Available Spare Blocks on PCIe SSDs)
  108.     $Warnings += $Output | Where-Object ID -eq 180 | Where-Object RawValue -lt 30 | Format-Table
  109.  
  110.     # Erase Failure Count
  111.     $Warnings += $Output | Where-Object ID -eq 182 | Where-Object RawValue -gt 1 | Format-Table
  112.  
  113.     # SATA Downshift Error Count or Runtime Bad Block (may indicate bad cable)
  114.     $Warnings += $Output | Where-Object ID -eq 183 | Where-Object RawValue -gt 2 | Format-Table
  115.  
  116.     # End-to-End error / IOEDC
  117.     $Warnings += $Output | Where-Object ID -eq 184 | Where-Object RawValue -ne 0 | Format-Table
  118.  
  119.     # Reported Uncorrectable Errors
  120.     $Warnings += $Output | Where-Object ID -eq 187 | Where-Object RawValue -gt 1 | Format-Table
  121.  
  122.     # Command Timeout
  123.     $Warnings += $Output | Where-Object ID -eq 188 | Where-Object RawValue -gt 1 | Format-Table
  124.  
  125.     # Temperature Celcius
  126.     $Warnings += $Output | Where-Object ID -eq 194 | Where-Object RawValue -gt 50 | Format-Table
  127.  
  128.     # Reallocation Event Count
  129.     $Warnings += $Output | Where-Object ID -eq 196 | Where-Object RawValue -gt 1 | Format-Table
  130.  
  131.     # Current Pending Sector Count
  132.     $Warnings += $Output | Where-Object ID -eq 197 | Where-Object RawValue -ne 0 | Format-Table
  133.  
  134.     # Uncorrectable Sector Count
  135.     $Warnings += $Output | Where-Object ID -eq 198 | Where-Object RawValue -ne 0 | Format-Table
  136.  
  137.     # UltraDMA CRC Error Count
  138.     $Warnings += $Output | Where-Object ID -eq 199 | Where-Object RawValue -ne 0 | Format-Table
  139.  
  140.     # Soft Read Error Rate
  141.     $Warnings += $Output | Where-Object ID -eq 201 | Where-Object Worst -lt 95 | Format-Table
  142.    
  143.     # SSD-specific ID's
  144.     if ($ssd) {
  145.         # SSD Percentage Lifetime Used % (Crucial/Micron)
  146.         $Warnings += $Output | Where-Object ID -eq 202 | Where-Object Worst -gt 95 | Format-Table
  147.  
  148.         # SSD RAIN Successful Recovery Page Count (Crucial Brand)
  149.         $Warnings += $Output | Where-Object ID -eq 210 | Where-Object Worst -gt 10 | Format-Table
  150.  
  151.         # SSD Life Left %
  152.         $Warnings += $Output | Where-Object ID -eq 231 | Where-Object Worst -lt 20 | Format-Table
  153.  
  154.         # SSD Endurance Remaining or Available Reserved Space %
  155.         $Warnings += $Output | Where-Object ID -eq 232 | Where-Object Worst -lt 20 | Format-Table
  156.  
  157.         # SSD Media Wear Out Indicator %
  158.         if ($disk -match 'intel') {
  159.             $Warnings += $Output | Where-Object ID -eq 233 | Where-Object Worst -lt 20 | Format-Table
  160.         }
  161.         else {
  162.             $Warnings += $Output | Where-Object ID -eq 233 | Where-Object RawValue -lt 20 | Format-Table
  163.         }
  164.     }
  165. } # End foreach
  166.  
  167. # Check FailurePredictStatus
  168. $Warnings += Get-CimInstance -Namespace 'Root\WMI' -ClassName 'MSStorageDriver_FailurePredictStatus' |
  169.     Select-Object InstanceName, PredictFailure, Reason |
  170.     Where-Object {$_.PredictFailure -ne $False} | Format-Table
  171.  
  172. # Check general disk status and health
  173. $Warnings += Get-PhysicalDisk |
  174.     Select-Object FriendlyName, Size, MediaType, OperationalStatus, HealthStatus |
  175.     Where-Object {$_.OperationalStatus -ne 'OK' -or $_.HealthStatus -ne 'Healthy'} | Format-Table
  176.  
  177. if ($Warnings) {
  178.     $Warnings = $warnings | Out-String
  179.     $Warnings
  180.     Rmm-Alert -Category 'Monitor - Drive SMART Values' -Body "$Warnings"
  181.     Exit 1
  182. }
  183.  
  184. if ($Error) {
  185.     if ($Error -match "Not supported") {
  186.         ($notsup = "Not supported: You may need to switch from ACHI to RAID/RST mode, see the link for how to do this non-destructively: https://www.top-password.com/blog/switch-from-raid-to-ahci-without-reinstalling-windows/")
  187.         Rmm-Alert -Category 'Monitor - Drive SMART Values' -Body "$notsup"
  188.     }
  189.     Rmm-Alert -Category 'Monitor - Drive SMART Values' -Body "$error"
  190.     exit 1
  191. }
  192.  
  193. Close-Rmm-Alert -Category "Monitor - Drive SMART Values"
  194.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement