mirror of
https://github.com/shirou/gopsutil.git
synced 2025-04-26 13:48:59 +08:00
Read disk model and serial from udev data or sysfs on Linux
It reads model and serial data directly from files instead of using `udevadm` command. This way obtaining the disk serial number doesn't depend on command execution, and can be also possible even if udev or udevadm are not available.
This commit is contained in:
parent
eeb1d38d69
commit
f03124bf86
@ -3,10 +3,11 @@
|
|||||||
package disk
|
package disk
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -385,26 +386,33 @@ func GetDiskSerialNumber(name string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetDiskSerialNumberWithContext(ctx context.Context, name string) string {
|
func GetDiskSerialNumberWithContext(ctx context.Context, name string) string {
|
||||||
n := fmt.Sprintf("--name=%s", name)
|
var stat unix.Stat_t
|
||||||
udevadm, err := exec.LookPath("/sbin/udevadm")
|
err := unix.Stat(name, &stat)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
major := unix.Major(stat.Rdev)
|
||||||
|
minor := unix.Minor(stat.Rdev)
|
||||||
|
|
||||||
out, err := invoke.CommandWithContext(ctx, udevadm, "info", "--query=property", n)
|
// Try to get the serial from udev data
|
||||||
|
udevDataPath := fmt.Sprintf("/run/udev/data/b%d:%d", major, minor)
|
||||||
// does not return error, just an empty string
|
if udevdata, err := ioutil.ReadFile(udevDataPath); err == nil {
|
||||||
if err != nil {
|
scanner := bufio.NewScanner(bytes.NewReader(udevdata))
|
||||||
return ""
|
for scanner.Scan() {
|
||||||
}
|
values := strings.Split(scanner.Text(), "=")
|
||||||
lines := strings.Split(string(out), "\n")
|
if len(values) == 2 && values[0] == "E:ID_SERIAL" {
|
||||||
for _, line := range lines {
|
return values[1]
|
||||||
values := strings.Split(line, "=")
|
}
|
||||||
if len(values) < 2 || values[0] != "ID_SERIAL" {
|
|
||||||
// only get ID_SERIAL, not ID_SERIAL_SHORT
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
return values[1]
|
}
|
||||||
|
|
||||||
|
// Try to get the serial from sysfs, look at the disk device (minor 0) directly
|
||||||
|
// because if it is a partition it is not going to contain any device information
|
||||||
|
devicePath := fmt.Sprintf("/sys/dev/block/%d:0/device", major)
|
||||||
|
model, _ := ioutil.ReadFile(filepath.Join(devicePath, "model"))
|
||||||
|
serial, _ := ioutil.ReadFile(filepath.Join(devicePath, "serial"))
|
||||||
|
if len(model) > 0 && len(serial) > 0 {
|
||||||
|
return fmt.Sprintf("%s_%s", string(model), string(serial))
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user