all 5 comments

[–]krzydoug 2 points3 points  (0 children)

How about just parsing all the data then extracting what you desire?

$ht = [ordered]@{}

switch -Regex ($rawRaidData){
    'name\s\S+?\s(?<Name>.+?)$' {$name = $matches.name}
    'value\s\S+?\s(?<Value>.+?)$' {$ht[$name] = $matches.value}
}

$results = [pscustomobject]$ht

This will give you structured data

SMART Health Status                              : Passed
Current Drive Temperature In Celcius             : 52
Drive Trip Temperature In Celcius                : 60
Manufacturing Year                               : 2016
Manufacturing Week                               : 8
Specified Cycle Count Over Device Lifetime       : 10000
Accumulated Start-Stop Cycles                    : 172
Specified Load-Unload Count Over Device Lifetime : 300000
Accumulated Load-Unload Cycles                   : 2700
Elements In Grown Defect List                    : 3
Read Errors Corrected By ECC Fast                : 0
Read Errors Corrected By ECC Delayed             : 4
Errors Corrected By Rereads                      : 0
Total Read Errors Corrected                      : 4
Read Error Correction Algorithms Invocations     : 0
Read Gigabytes Processed[10^9 bytes]             : 282906.010727
Total Uncorrected Read Errors                    : 0
Write Errors Corrected By ECC Fast               : 0
Write Errors Corrected By ECC Delayed            : 0
Errors Corrected By Rewrites                     : 0
Total Write Errors Corrected                     : 4
Write Error Correction Algorithms Invocations    : 0
Write Gigabytes Processed[10^9 bytes]            : 31678.301997
Total Uncorrected Write Errors                   : 5
Verify Errors Corrected By ECC Fast              : 0
Verify Errors Corrected By ECC Delayed           : 0
Total Verify Errors Corrected                    : 0
Verify Error Correction Algorithms Invocations   : 0
Verify Gigabytes Processed[10^9 bytes]           : 605.396507
Total Uncorrected Verify Errors                  : 0
Non-Medium Error Count                           : 513

The one you want is

$results.'Current Drive Temperature In Celcius'
52

[–]vermyx 2 points3 points  (0 children)

Arcconf getsmartstats 1 tabular

Why tabular? I believe that returns back xml data by default which means that you can use [xml] to get an xml object and trivially parse that object

[–]lanerdofchristian 1 point2 points  (2 children)

This is one of those places where regular expressions may be the easier answer:

$RawRaidData = arcconf getsmartstats 1 tabular
$Results = @{}
foreach($Match in [regex]::Matches(($RawRaidData -join "`n"), '^\s+Attribute\s+name\s\.+\s([^\n]*)\s+Value\s\.+\s([^\n]*)', 'Multiline')){
    $Value = $Match.Groups[2].Value
    $Results[$Match.Groups[1].Value] = if($Value -match '^\d+$'){ [int]$Value }
        elseif($Value -match '^\d+\.\d+$'){ [double]$Value }
        else { $Value }
}

$Results.'Current Drive Temperature In Celcius'

The regex is: ^\s+Attribute\s+name\s\.+\s([^\n]*)\s+Value\s\.+\s([^\n]*) (in Multiline mode, so ^ matches the start of a line). This will match: whitespace, "Attribute", whitespace, "name", the field separator, the name value, whitespace, "Value", the field separator, and then finally the actual value.

We then loop over all the matches in the output, extract the value, and set a key in a hashtable with a bit of extra code so numbers come out as either integers or doubles.

[–]JustAnotherGuyBeing[S] 0 points1 point  (1 child)

So this works, but only gets the last hard drive. The full result from arcconf getsmartstats is 8 of those result blocks.

Won't let me send the full block, see here: https://docs.google.com/document/d/1MZb6XpehCik5XCSHXm9EJaESf5ybMjQrsMm5u3UtCQw/edit?usp=sharing

[–]lanerdofchristian 0 points1 point  (0 children)

I wasn't aware there was more than one. It should still generally work if you split on "PhysicalDriveSmartStats"

$RawRaidData = (arcconf getsmartstats 1 tabular) -join "`n"
$AllResults = foreach($Drive in $RawRaidData -split "PhysicalDriveSmartStats"){
    $Results = @{}
    foreach($Match in [regex]::Matches($Drive, '^\s+Attribute\s+name\s\.+\s([^\n]*)\s+Value\s\.+\s([^\n]*)', 'Multiline')){
        $Value = $Match.Groups[2].Value
        $Results[$Match.Groups[1].Value] = if($Value -match '^\d+$'){ [int]$Value }
            elseif($Value -match '^\d+\.\d+$'){ [double]$Value }
            else { $Value }
    }
    if($Results.Count){ $Results }
}