init
This commit is contained in:
commit
7499595649
36
disks.go
Normal file
36
disks.go
Normal file
@ -0,0 +1,36 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
)
|
||||
|
||||
func getDisks() *Devices {
|
||||
rawout := execSystem("lsblk", "-dJ", "-I 8")
|
||||
if rawout == nil {
|
||||
log.Fatal("")
|
||||
}
|
||||
var parsed Devices
|
||||
|
||||
// decoding country1 struct
|
||||
// from json format
|
||||
err := json.Unmarshal(rawout, &parsed)
|
||||
|
||||
if err != nil {
|
||||
// if error is not nil
|
||||
// print error
|
||||
fmt.Println(err)
|
||||
}
|
||||
return &parsed
|
||||
}
|
||||
|
||||
type BlockDevice struct {
|
||||
Name string `json:"name"`
|
||||
Size string `json:"size"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
type Devices struct {
|
||||
Blockdevices []BlockDevice `json:"blockdevices"`
|
||||
}
|
43
main.go
Normal file
43
main.go
Normal file
@ -0,0 +1,43 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func execSystem(cmd string, args ...string) []byte {
|
||||
com := exec.Command(cmd, args...)
|
||||
var out bytes.Buffer
|
||||
com.Stdout = &out
|
||||
com.Stderr = &out
|
||||
|
||||
err := com.Run()
|
||||
|
||||
if out.Bytes() == nil {
|
||||
fmt.Println(out.String())
|
||||
log.Fatal(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
return out.Bytes()
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println("Running smart check on all disks")
|
||||
|
||||
disks := getDisks()
|
||||
for _, blockdevice := range disks.Blockdevices {
|
||||
fmt.Printf("\nChecking /dev/%s\n", blockdevice.Name)
|
||||
|
||||
path := fmt.Sprintf("/dev/%s", blockdevice.Name)
|
||||
|
||||
info := getDiskInfo(path)
|
||||
fmt.Printf("%s %s\n", info.ModelFamily, info.ModelName)
|
||||
|
||||
checkSmartAttributes(path, strings.Contains(strings.ToLower(info.ModelName+info.ModelFamily), strings.ToLower("Seagate")), info.RotationRate != 0)
|
||||
}
|
||||
|
||||
}
|
101
smartdiskinfo.go
Normal file
101
smartdiskinfo.go
Normal file
@ -0,0 +1,101 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type DiskInfo struct {
|
||||
ModelFamily string `json:"model_family"`
|
||||
ModelName string `json:"model_name"`
|
||||
SerialNumber string `json:"serial_number"`
|
||||
RotationRate uint `json:"rotation_rate"`
|
||||
}
|
||||
|
||||
func getDiskInfo(diskpath string) *DiskInfo {
|
||||
rawsmart := execSystem("smartctl", "-i", "-json", diskpath)
|
||||
if rawsmart == nil {
|
||||
fmt.Println("error while getting smart info")
|
||||
}
|
||||
|
||||
var info DiskInfo
|
||||
|
||||
// decoding country1 struct
|
||||
// from json format
|
||||
err := json.Unmarshal(rawsmart, &info)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
return &info
|
||||
}
|
||||
|
||||
type Item struct {
|
||||
Name string `json:"name"`
|
||||
Raw struct {
|
||||
Value uint64 `json:"value"`
|
||||
} `json:"raw"`
|
||||
}
|
||||
|
||||
func checkSmartAttributes(diskpath string, isSeagate bool, isHdd bool) {
|
||||
rawsmart := execSystem("smartctl", "-A", "-json", diskpath)
|
||||
if rawsmart == nil {
|
||||
fmt.Println("error while getting smart info")
|
||||
}
|
||||
|
||||
type RawAttr struct {
|
||||
AtaSmartAttr struct {
|
||||
Table []Item `json:"table"`
|
||||
} `json:"ata_smart_attributes"`
|
||||
}
|
||||
|
||||
var rawattr RawAttr
|
||||
|
||||
err := json.Unmarshal(rawsmart, &rawattr)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
rrerrrate := getItemValue(rawattr.AtaSmartAttr.Table, "Raw_Read_Error_Rate")
|
||||
// seagate hdds have a special way to represent their error rates
|
||||
if isSeagate {
|
||||
// [--16bits---|---32bits---]
|
||||
// error count| operation count
|
||||
rrerrrate = rrerrrate >> 32
|
||||
}
|
||||
fmt.Println("Raw_Read_Error_Rate: " + evalStrZero(rrerrrate))
|
||||
fmt.Println("Reallocated_Sector_Ct: " + evalStrZero(getItemValue(rawattr.AtaSmartAttr.Table, "Reallocated_Sector_Ct")))
|
||||
|
||||
// there are some additinoal hdd smart values
|
||||
if isHdd {
|
||||
rrerrrate = getItemValue(rawattr.AtaSmartAttr.Table, "Seek_Error_Rate")
|
||||
if isSeagate {
|
||||
// [--16bits---|---32bits---]
|
||||
// error count| operation count
|
||||
rrerrrate = rrerrrate >> 32
|
||||
}
|
||||
fmt.Println("Seek_Error_Rate: " + evalStrZero(rrerrrate))
|
||||
fmt.Println("Spin_Retry_Count: " + evalStrZero(getItemValue(rawattr.AtaSmartAttr.Table, "Spin_Retry_Count")))
|
||||
fmt.Println("Spin_Up_Time: " + evalStrZero(getItemValue(rawattr.AtaSmartAttr.Table, "Spin_Up_Time")))
|
||||
}
|
||||
|
||||
fmt.Println(rawattr)
|
||||
}
|
||||
|
||||
func evalStrZero(nr uint64) string {
|
||||
if nr == 0 {
|
||||
return "\tPASS"
|
||||
} else {
|
||||
return fmt.Sprintf("\tFAIL :: raw value=%d", nr)
|
||||
}
|
||||
}
|
||||
|
||||
func getItemValue(arr []Item, name string) uint64 {
|
||||
for i := range arr {
|
||||
if arr[i].Name == name {
|
||||
return arr[i].Raw.Value
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
Loading…
Reference in New Issue
Block a user