Skip to content

Pure-Go library to access drive's S.M.A.R.T. information

License

Notifications You must be signed in to change notification settings

anatol/smart.go

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

35 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

smart.go

Smart.go is a pure Golang library to access disk low-level S.M.A.R.T. information. Smart.go tries to match functionality provided by smartctl but with golang API.

Currently this library support SATA, SCSI and NVMe drives. Different drive types provide different set of monitoring information and API reflects it.

At this point the library works at Linux and partially at MacOSX. We are looking for help with porting it to other platforms.

Example

Here is an example of code that demonstrates the library usage.

// skip the error handling for more compact API example
dev, _ := smart.OpenNVMe("/dev/nvme0n1")
c, nss, _ := dev.Identify()
fmt.Println("Model number: ", c.ModelNumber())
fmt.Println("Serial number: ", c.SerialNumber())
fmt.Println("Size: ", c.Tnvmcap.Val[0])

// namespace #1
ns := nss[0]
fmt.Println("Namespace 1 utilization: ", ns.Nuse*ns.LbaSize())

sm, _ := dev.ReadSMART()
fmt.Println("Temperature: ", sm.Temperature, "K")
// PowerOnHours is reported as 128-bit value and represented by this library as an array of uint64
fmt.Println("Power-on hours: ", sm.PowerOnHours.Val[0])
fmt.Println("Power cycles: ", sm.PowerCycles.Val[0])

The output looks like

Model number:  SAMSUNG MZVLB512HBJQ-000L7
Serial number:  S4ENNF0M741521
Size:  512110190592
Namespace 1 utilization:  387524902912
Temperature:  327 K
Power-on hours:  499
Power cycles:  1433

Here is an example of iterating over system's block devices:

block, err := ghw.Block()
if err != nil {
  panic(err)
}
for _, disk := range block.Disks {
        dev, err := smart.Open("/dev/" + disk.Name)
        if err != nil {
            // some devices (like dmcrypt) do not support SMART interface
            fmt.Println(err)
            continue
        }
        defer dev.Close()

        switch sm := dev.(type) {
        case *smart.SataDevice:
            data, err := sm.ReadSMARTData()
            attr, ok := data.Attrs[194]; ok { // attr.Name == "Temperature_Celsius"
                temp, min, max, overtempCounter, err := attr.ParseAsTemperature()
                // min/max/counter are optional
            }
        case *smart.ScsiDevice:
            _, _ = sm.Capacity()
        case *smart.NVMeDevice:
            _, _ = sm.ReadSMART()
        }
}

Reading generic SMART attributes.

smart.go provides API for easier access to the most commonly used device attributes.

dev, err := smart.Open("/dev/nvme0n1")
require.NoError(t, err)
defer dev.Close()

a, err := dev.ReadGenericAttributes()
require.NoError(t, err)

fmt.Println("The temperature is ", a.Temperature) // in Celsius
fmt.Println("Read block count ", a.Read)
fmt.Println("Written block count ", a.Written)
fmt.Println("Power Cycles count ", a.PowerCycles)
fmt.Println("Power On Hours ", a.PowerOnHours)

Credit

This project is inspired by https://github.com/dswarbrick/smart