How to read HDD S.M.A.R.T. attributes?
Asked Answered
S

5

7

I would monitoring the smart HDD-s on my Windows 7 clients.

I would to get the HDD smart attributes without using any vbs file or ready-made tool just looking towards WMI or PowerShell.

I would aggregate that data with ZABBIX monitoring server (use zabbix-sender.exe).

I found a more or less solution for Linux, but I would monitor windows 7 machines HDD.

Has anyone an idea?

Subtropical answered 31/3, 2014 at 9:56 Comment(0)
D
4

--- Preface: ---

I believe that a PowerShell solution would meet your needs. Unfortunately, there doesn't appear to be a way of obtaining all S.M.A.R.T. information available from various storage devices via PowerShell only, as PowerShell's is a rather generic implentation of the functionality, and S.M.A.R.T. is varied in its implementation across storage device vendors.

Having said that, the method described below should satisfy the key requirements of typical S.M.A.R.T. checks performed by users, including predicted lifespan, reallocated and uncorrectable sectors, etc., though using rather generic PowerShell terminology (e.g. lifespan = "Wear").

--- Information: ---

With a combination of two PowerShell cmdlets, we can easily view some of the the S.M.A.R.T. data offered by storage devices:

Get-StorageReliabilityCounter

"The Get-StorageReliabilityCounter cmdlet gets the storage reliability counters for the specified disk or physical disk. These counters include information about such things as the device temperature, errors, wear, and length of time the device has been in use."

This is the cmdlet that will actually return the S.M.A.R.T data we seek. However, unlike many other cmdlets you may be familiar with, this cmdlet needs to be pointed to the target disk(s) by way of a PowerShell object(s). (If you're new to PowerShell, this is not as complex as it may sound, so fear not.)

Get-Disk

"The Get-Disk cmdlet gets one or more Disk objects visible to the operating system, or optionally a filtered list."

This is the cmdlet we will use to provide the required PowerShell object(s), so that Get-StorageReliabilityCounter knows which disk(s) to query.

--- Code: ---

As with anything, there are multiple ways to actually execute the code, so I'm just going to provide code to obtain the desired information in the simplest way possible, in my opinion.

For simple S.M.A.R.T. information on all local disks (run as Administrator):

Get-Disk | Get-StorageReliabilityCounter

Sample output:

PS C:\WINDOWS\system32> Get-Disk | Get-StorageReliabilityCounter

DeviceId Temperature ReadErrorsUncorrected Wear PowerOnHours
-------- ----------- --------------------- ---- ------------
1                    0                     0    5505
2                    0                     0    572
0                                          0    2799

For extended S.M.A.R.T. information on all local disks (run as Administrator):

 Get-Disk | Get-StorageReliabilityCounter | Select-Object -Property "*"

Truncated sample output:

PS C:\WINDOWS\system32> Get-Disk | Get-StorageReliabilityCounter | Select-Object -Property "*"

DeviceId                : 1
FlushLatencyMax         : 46
LoadUnloadCycleCount    :
LoadUnloadCycleCountMax :
ManufactureDate         :
PowerOnHours            : 5505
ReadErrorsCorrected     : 0
ReadErrorsTotal         : 0
ReadErrorsUncorrected   : 0
ReadLatencyMax          : 231
StartStopCycleCount     :
StartStopCycleCountMax  :
Temperature             : 27
TemperatureMax          : 0
Wear                    : 0
WriteErrorsCorrected    :
WriteErrorsTotal        :
WriteErrorsUncorrected  :
WriteLatencyMax         : 69
PSComputerName          :

As you can see, listed are some of those desirable indicators that may or may not allow you to circumvent disaster.

--- tl;dr: ---

Run

Get-Disk | Get-StorageReliabilityCounter

or

Get-Disk | Get-StorageReliabilityCounter | Select-Object -Property "*"

as Administrator to get most important S.M.A.R.T. information.

Diadromous answered 10/1, 2020 at 5:4 Comment(0)
F
3

Use the WMI API to access SMART data like so,

gwmi -namespace root\wmi -class MSStorageDriver_FailurePredictStatus

There are more examples in the net.

Frasier answered 31/3, 2014 at 10:19 Comment(1)
Unfortunately it is not provide enough informaiton. I would get ID based vaues. Like 03 - spin_up_time 00Subtropical
A
2

Here's a powershell script that extracts all the attribute data from smartctl (smartmontools) output. Adjust the path to smartctl if it's not in your %path%.

It can be used like this:

.\get-smart.ps1 -Drive hda -AttributeId 5,241 -Property Name,Raw -FriendlyOutput

or just

.\get-smart.ps1 hda 5,241 Name,Raw -f

etc. If you specify -FriendlyOutput it formats the data as table, otherwise it gives you an object. If you're just interested in a specific value, use

.\get-smart.ps1 hda 241 Raw

Note that some properties, such as threshold, are not present if smartctl is not run as administrator.

No exception handling yet! You have been warned!

param(
    [Parameter(Mandatory=$True)]
    [string]    $Drive,
    [int[]]     $AttributeId,
    [string[]]  $Property,
    [switch]    $FriendlyOutput)
# parses attribute table in smartctl output and builds an object
$smart = [string[]](smartctl -A $Drive)
$attributes=@()
foreach ($s in $smart) {
    if ($s -match '^\s*(\d+)\s+(\w+)\s+(\w+)\s+(\d+)\s+(\d+)\s+([\d-]+)\s+([\w-]+)\s+(\w+)\s+([\w-]+)\s+(\d+)') {
        $o = new-object -Typename PSObject
        add-member -in $o -m NoteProperty -name 'ID' -value ([int]$matches[1])
        add-member -in $o -m NoteProperty -name 'Name' -value $matches[2]
        add-member -in $o -m NoteProperty -name 'Flag' -value $matches[3]
        add-member -in $o -m NoteProperty -name 'Value' -value ([int]$matches[4])
        add-member -in $o -m NoteProperty -name 'Worst' -value ([int]$matches[5])
        add-member -in $o -m NoteProperty -name 'Threshold' -value ([int]$matches[6])
        add-member -in $o -m NoteProperty -name 'Type' -value $matches[7]
        add-member -in $o -m NoteProperty -name 'Updated' -value $matches[8]
        add-member -in $o -m NoteProperty -name 'WhenFailed' -value $matches[9]
        add-member -in $o -m NoteProperty -name 'Raw' -value ([int64]$matches[10])
        $attributes += $o
    }
}
if ($AttributeId){
    $attributes = $attributes | ? {$_.id -in $attributeid}
}
if ($Property){
    if ($property.count -gt 1 -and $attributes.count -gt -0 -and $Property -notcontains 'id'){
        # if more than one result and more than one attribute, add the ID to the output
        $property = ,'id'+$Property
    }
    $attributes = $attributes | select $Property
}
if (@($attributes).count -eq 1 -and @($attributes.psobject.properties).count -eq 1){
    # return single values directly instead of an object
    $attributes.psobject.properties.value
} elseif ($FriendlyOutput){
    $attributes | ft * -a
} else {
    $attributes
}
Anabolism answered 17/2, 2015 at 20:39 Comment(1)
The complex (error prone) parsing script is no longer needed, just use the JSON output mode of smartctl.Interpleader
I
2

Using the JSON output mode of Smartmontools this can be done easily:

The following short Powershell script read the SMART attributes for the first disk (named /dev/sda in smartmontools) and selects the attribute with ID 241 (that is Total_LBAs_Written on my SSD).

The last line converts the LBA value to the TBW value (TeraByte(s) Written).

$json = (smartctl -A -j /dev/sda | ConvertFrom-JSON)
$lbaRaw = ($json.ata_smart_attributes.table | Where id -eq 241 | Select-Object raw)
$tbw = $lbaRaw.raw.value * 512 / 1024 / 1024 / 1024 / 1024
$tbw.toString("##.## TB")
Interpleader answered 21/3, 2019 at 19:36 Comment(0)
L
0

This gets a useful view of the SMART values in one table, so you can map which drive has which values.

$Disks = Get-PhysicalDisk
$DiskTable = $Disks | Select-Object -Property FriendlyName,SerialNumber,UniqueId,FirmwareVersion,
    MediaType,Size,PhysicalSectorSize,LogicalSectorSize,
    @{Name="ReadErrorsCorrected";Expression={""}},@{Name="ReadErrorsUncorrected";Expression={""}},
    @{Name="ReadLatencyMax";Expression={""}},@{Name="WriteLatencyMax";Expression={""}},
    @{Name="Temperature";Expression={""}},@{Name="PowerOnHours";Expression={""}},
    @{Name="Wear";Expression={""}}
for ( $i=0 ; $i -lt $Disks.Count ; $i++ ) {
    $DiskReliability = $Disks[$i] | Get-StorageReliabilityCounter | 
        Select-Object -Property ReadErrorsCorrected,ReadErrorsUncorrected,ReadLatencyMax,
            WriteLatencyMax,Temperature,PowerOnHours,Wear
    $DiskTable[$i].ReadErrorsCorrected = $DiskReliability.ReadErrorsCorrected
    $DiskTable[$i].ReadErrorsUncorrected = $DiskReliability.ReadErrorsUncorrected
    $DiskTable[$i].ReadLatencyMax = $DiskReliability.ReadLatencyMax
    $DiskTable[$i].WriteLatencyMax = $DiskReliability.WriteLatencyMax
    $DiskTable[$i].Temperature = $DiskReliability.Temperature
    $DiskTable[$i].PowerOnHours = $DiskReliability.PowerOnHours
    $DiskTable[$i].Wear = $DiskReliability.Wear
}
$DiskTable | Out-GridView
Lithography answered 12/5, 2021 at 21:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.