【问题标题】:How to read HDD S.M.A.R.T. attributes?如何读取 HDD S.M.A.R.T.属性?
【发布时间】:2014-05-10 14:50:16
【问题描述】:

我会监控我的 Windows 7 客户端上的智能硬盘。

我会在不使用任何 vbs 文件或现成工具的情况下获得 HDD 智能属性,而只是查看 WMI 或 PowerShell。

我会将这些数据与 ZABBIX 监控服务器聚合(使用 zabbix-sender.exe)。

我找到了或多或少的 Linux 解决方案,但我会监控 windows 7 机器的硬盘。

有人有想法吗?

【问题讨论】:

    标签: powershell windows-7 wmi monitoring zabbix


    【解决方案1】:

    像这样使用 WMI API 访问 SMART 数据,

    gwmi -namespace root\wmi -class MSStorageDriver_FailurePredictStatus
    

    Thereexamples 更多。

    【讨论】:

    • 不幸的是,它没有提供足够的信息。我会得到基于 ID 的值。喜欢 03 - spin_up_time 00
    【解决方案2】:

    --- 前言: ---

    我相信 PowerShell 解决方案可以满足您的需求。不幸的是,似乎没有办法获得all S.M.A.R.T。只能通过 PowerShell 从各种存储设备获得信息,因为 PowerShell 是该功能的相当通用的实现,而 S.M.A.R.T.不同存储设备供应商的实施方式各不相同。

    话虽如此,下面描述的方法应该满足典型 S.M.A.R.T. 的关键要求。用户执行的检查,包括预测寿命、重新分配和不可纠正的扇区等,尽管使用了相当通用的 PowerShell 术语(例如 lifespan = "Wear")。

    --- 信息: ---

    结合使用两个 PowerShell cmdlet,我们可以轻松查看一些 S.M.A.R.T.存储设备提供的数据:

    Get-StorageReliabilityCounter

    "Get-StorageReliabilityCounter cmdlet 获取存储可靠性 指定磁盘或物理磁盘的计数器。这些计数器 包括有关设备温度等信息, 错误、磨损和设备使用的时间长度。”

    这个 cmdlet 将实际返回我们寻找的 S.M.A.R.T 数据。但是,与您可能熟悉的许多其他 cmdlet 不同,此 cmdlet 需要通过 PowerShell 对象指向目标磁盘。 (如果您是 PowerShell 新手,这并不像听起来那么复杂,所以不要害怕。)

    Get-Disk

    Get-Disk cmdlet 获取一个或多个磁盘对象,对 操作系统,或可选的过滤列表。”

    这是我们将用来提供所需 PowerShell 对象的 cmdlet,以便 Get-StorageReliabilityCounter 知道要查询哪些磁盘。

    --- 代码: ---

    与任何事情一样,有多种方法可以实际执行代码,因此在我看来,我将提供代码以尽可能最简单的方式获取所需信息。

    对于简单的 S.M.A.R.T.所有本地磁盘的信息(以管理员身份运行):

    Get-Disk | Get-StorageReliabilityCounter
    

    样本输出:

    PS C:\WINDOWS\system32> Get-Disk | Get-StorageReliabilityCounter
    
    DeviceId Temperature ReadErrorsUncorrected Wear PowerOnHours
    -------- ----------- --------------------- ---- ------------
    1                    0                     0    5505
    2                    0                     0    572
    0                                          0    2799
    

    适用于扩展 S.M.A.R.T.所有本地磁盘的信息(以管理员身份运行):

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

    截断样本输出:

    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          :
    

    如您所见,列出了一些可取的指标,它们可能会或可能不会让您规避灾难。

    --- tl;dr: ---

    运行

    Get-Disk | Get-StorageReliabilityCounter
    

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

    作为管理员获得最重要的 S.M.A.R.T.信息。

    【讨论】:

      【解决方案3】:

      这是一个 powershell 脚本,它从 smartctl (smartmontools) 输出中提取所有属性数据。如果 smartctl 不在您的 %path% 中,请调整路径。

      可以这样使用:

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

      或者只是

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

      等等。如果您指定 -FriendlyOutput,它会将数据格式化为表格,否则它会为您提供一个对象。 如果您只对特定值感兴趣,请使用

      .\get-smart.ps1 hda 241 Raw
      

      请注意,如果 smartctl 未以管理员身份运行,则某些属性(例如阈值)不存在。

      还没有异常处理!您已被警告!

      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
      }
      

      【讨论】:

      • 不再需要复杂(容易出错)的解析脚本,只需使用smartctl的JSON输出方式即可。
      【解决方案4】:

      使用Smartmontools的JSON输出模式可以轻松完成:

      以下简短的 Powershell 脚本读取第一个磁盘的 SMART 属性(在 smartmontools 中名为 /dev/sda)并选择 ID 为 241 的属性(即我的 SSD 上的 Total_LBAs_Written)。

      最后一行将 LBA 值转换为 TBW 值(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")
      

      【讨论】:

        【解决方案5】:

        这会在一个表中获得 SMART 值的有用视图,因此您可以映射哪个驱动器具有哪些值。

        $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
        

        【讨论】:

          猜你喜欢
          • 2013-01-19
          • 2014-11-01
          • 2013-09-01
          • 1970-01-01
          • 2011-12-16
          • 1970-01-01
          • 2018-04-18
          • 2015-02-06
          • 2014-02-04
          相关资源
          最近更新 更多