From 6ab3ee0124cf5cc8d5b755e691f6005ab509a511 Mon Sep 17 00:00:00 2001 From: Daniel Legt Date: Sat, 20 Jan 2024 00:21:59 +0200 Subject: [PATCH] Initial Commit --- go.mod | 8 ++++++ go.sum | 4 +++ lib/hardware/logic.go | 62 +++++++++++++++++++++++++++++++++++++++++++ lib/hardware/type.go | 46 ++++++++++++++++++++++++++++++++ main.go | 20 ++++++++++++++ 5 files changed, 140 insertions(+) create mode 100644 go.mod create mode 100644 go.sum create mode 100644 lib/hardware/logic.go create mode 100644 lib/hardware/type.go create mode 100644 main.go diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..7851cbe --- /dev/null +++ b/go.mod @@ -0,0 +1,8 @@ +module tea.chunkbyte.com/kato/drive-health + +go 1.21.6 + +require ( + github.com/anatol/smart.go v0.0.0-20230705044831-c3b27137baa3 // indirect + golang.org/x/sys v0.9.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..f12b43a --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +github.com/anatol/smart.go v0.0.0-20230705044831-c3b27137baa3 h1:kAF2MWFD8tyDqD74OQizymjj2cnZAURwSzBrEslCDnI= +github.com/anatol/smart.go v0.0.0-20230705044831-c3b27137baa3/go.mod h1:llkexGSe52bW0OjNva0kvIqGZxfSnVfpKHrnKBI2+pU= +golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= +golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/lib/hardware/logic.go b/lib/hardware/logic.go new file mode 100644 index 0000000..1cf16ef --- /dev/null +++ b/lib/hardware/logic.go @@ -0,0 +1,62 @@ +package hardware + +import ( + "bufio" + "bytes" + "fmt" + "os/exec" + "strings" +) + +func GetSystemHardDrives() ([]HardDrive, error) { + + // Execute the lsblk command to get detailed block device information + cmd := exec.Command("lsblk", "-d", "-o", "NAME,TRAN,SIZE,MODEL,SERIAL,TYPE") + var out bytes.Buffer + cmd.Stdout = &out + err := cmd.Run() + if err != nil { + fmt.Println("Failed to execute command:", err) + return nil, err + } + + var hardDrives []HardDrive + + // Scan the output line by line + scanner := bufio.NewScanner(&out) + for scanner.Scan() { + line := scanner.Text() + + // Skip the header line + if strings.Contains(line, "NAME") { + continue + } + + // Split the line into columns + cols := strings.Fields(line) + if len(cols) < 6 { + continue + } + + // Filter out nvme drives (M.2) + if cols[1] != "nvme" { + hd := HardDrive{ + Name: cols[0], + Transport: cols[1], + Size: cols[2], + Model: cols[3], + Serial: cols[4], + Type: cols[5], + Temperature: 0, + } + hardDrives = append(hardDrives, hd) + } + } + + // Handle error + if err := scanner.Err(); err != nil { + return nil, err + } + + return hardDrives, nil +} diff --git a/lib/hardware/type.go b/lib/hardware/type.go new file mode 100644 index 0000000..b0d17c0 --- /dev/null +++ b/lib/hardware/type.go @@ -0,0 +1,46 @@ +package hardware + +import ( + "fmt" + + "github.com/anatol/smart.go" +) + +type HardDrive struct { + Name string + Transport string + Size string + Model string + Serial string + Type string + Temperature int +} + +// Fetch the temperature of the device, optinally update the reference object +func (h *HardDrive) GetTemperature(updateTemp bool) int { + // Fetch the device by name + disk, err := smart.Open("/dev/" + h.Name) + if err != nil { + fmt.Printf("Failed to open device %s: %s\n", h.Name, err) + return -1 + } + defer disk.Close() + + // Fetch SMART data + smartInfo, err := disk.ReadGenericAttributes() + if err != nil { + fmt.Printf("Failed to get SMART data for %s: %s\n", h.Name, err) + return -1 + } + + // Parse the temperature + temperature := int(smartInfo.Temperature) + + // Optionally update the reference object's temperature + if updateTemp { + h.Temperature = temperature + } + + // Return the found value + return temperature +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..683c532 --- /dev/null +++ b/main.go @@ -0,0 +1,20 @@ +package main + +import ( + "fmt" + + "tea.chunkbyte.com/kato/drive-health/lib/hardware" +) + +func main() { + + hardDrives, err := hardware.GetSystemHardDrives() + if err != nil { + panic(err) + } + + for _, hdd := range hardDrives { + fmt.Printf("%s %s [%s]: %vC\n", hdd.Model, hdd.Serial, hdd.Size, hdd.GetTemperature(true)) + } + +}