safesight-edge/agent/internal/sysinfo/sysinfo.go
sladro 5f69321b40
Some checks are pending
CI / host-build (push) Waiting to run
CI / rk3588-cross-build (push) Waiting to run
准备测试agent服务能力
2026-01-10 09:27:13 +08:00

167 lines
3.1 KiB
Go

package sysinfo
import (
"bufio"
"crypto/rand"
"encoding/hex"
"errors"
"fmt"
"net"
"os"
"path/filepath"
"runtime"
"strconv"
"strings"
"time"
"rk3588sys/agent/internal/files"
)
func Hostname() string {
h, err := os.Hostname()
if err != nil {
return ""
}
return h
}
func UptimeSec() int64 {
if runtime.GOOS != "linux" {
return 0
}
b, err := os.ReadFile("/proc/uptime")
if err != nil {
return 0
}
fields := strings.Fields(string(b))
if len(fields) == 0 {
return 0
}
f, err := strconv.ParseFloat(fields[0], 64)
if err != nil {
return 0
}
if f < 0 {
return 0
}
return int64(f)
}
func DeviceID(deviceIDPath string) (string, error) {
if id, err := readFirstLine("/etc/machine-id"); err == nil {
id = strings.TrimSpace(id)
if id != "" {
return id, nil
}
}
if strings.TrimSpace(deviceIDPath) == "" {
return "", errors.New("device_id_path is empty")
}
if id, err := readFirstLine(deviceIDPath); err == nil {
id = strings.TrimSpace(id)
if id != "" {
return id, nil
}
}
id, err := newUUID()
if err != nil {
return "", err
}
if err := files.EnsureDir(filepath.Dir(deviceIDPath), 0o755); err != nil {
return "", err
}
if err := files.WriteFileAtomic(deviceIDPath, []byte(id+"\n"), 0o644); err != nil {
return "", fmt.Errorf("persist device_id: %w", err)
}
return id, nil
}
func PrimaryIPv4() string {
ifaces, err := net.Interfaces()
if err != nil {
return ""
}
for _, iface := range ifaces {
if (iface.Flags&net.FlagUp) == 0 || (iface.Flags&net.FlagLoopback) != 0 {
continue
}
addrs, err := iface.Addrs()
if err != nil {
continue
}
for _, a := range addrs {
ip := addrIP(a)
if ip == nil {
continue
}
v4 := ip.To4()
if v4 == nil || v4.IsLoopback() {
continue
}
return v4.String()
}
}
return ""
}
func LocalIPTo(remoteIP string) (string, error) {
raddr := &net.UDPAddr{IP: net.ParseIP(remoteIP), Port: 9}
if raddr.IP == nil {
return "", fmt.Errorf("invalid remote ip: %q", remoteIP)
}
c, err := net.DialUDP("udp4", nil, raddr)
if err != nil {
return "", err
}
defer c.Close()
_ = c.SetDeadline(time.Now().Add(200 * time.Millisecond))
if la, ok := c.LocalAddr().(*net.UDPAddr); ok {
if la.IP != nil {
if v4 := la.IP.To4(); v4 != nil {
return v4.String(), nil
}
}
}
return "", errors.New("failed to determine local ip")
}
func readFirstLine(path string) (string, error) {
f, err := os.Open(path)
if err != nil {
return "", err
}
defer f.Close()
s := bufio.NewScanner(f)
if !s.Scan() {
if err := s.Err(); err != nil {
return "", err
}
return "", errors.New("empty")
}
return s.Text(), nil
}
func addrIP(a net.Addr) net.IP {
switch v := a.(type) {
case *net.IPNet:
return v.IP
case *net.IPAddr:
return v.IP
default:
return nil
}
}
func newUUID() (string, error) {
b := make([]byte, 16)
if _, err := rand.Read(b); err != nil {
return "", fmt.Errorf("rand: %w", err)
}
b[6] = (b[6] & 0x0f) | 0x40
b[8] = (b[8] & 0x3f) | 0x80
hexStr := hex.EncodeToString(b)
return fmt.Sprintf("%s-%s-%s-%s-%s", hexStr[0:8], hexStr[8:12], hexStr[12:16], hexStr[16:20], hexStr[20:32]), nil
}