diff --git a/conf/config.toml b/conf/config.toml index 17d3b8cf..13bf40e6 100644 --- a/conf/config.toml +++ b/conf/config.toml @@ -7,6 +7,7 @@ print_configs = false # "xx" -> use specified string xx # "$hostname" -> auto detect hostname # "$ip" -> auto detect ip +# "$sn" -> auto detect bios serial number # "$hostname-$ip" -> auto detect hostname and ip to replace the vars hostname = "" @@ -30,6 +31,7 @@ concurrency = -1 [global.labels] # region = "shanghai" # env = "localhost" +# sn = "$sn" [log] # file_name is the file to write logs to diff --git a/config/config.go b/config/config.go index 8db7003f..882b2380 100644 --- a/config/config.go +++ b/config/config.go @@ -6,6 +6,7 @@ import ( "net" "net/url" "os" + "os/exec" "path" "runtime" "strings" @@ -192,6 +193,7 @@ func (c *ConfigType) GetHostname() string { ret = strings.Replace(ret, "$hostname", name, -1) ret = strings.Replace(ret, "$ip", c.GetHostIP(), -1) + ret = strings.Replace(ret, "$sn", c.GetHostSN(), -1) ret = os.Expand(ret, GetEnv) return ret @@ -204,7 +206,14 @@ func (c *ConfigType) GetHostIP() string { return ret } +func (c *ConfigType) GetHostSN() string { + ret := HostInfo.GetSN() + if ret == "" { + return c.GetHostname() + } + return ret +} func GetEnv(key string) string { v := os.Getenv(key) return envVarEscaper.Replace(v) @@ -300,6 +309,29 @@ func GetOutboundIP() (net.IP, error) { return localAddr.IP, nil } +func GetBiosSn() (string, error) { + sn := "" + if runtime.GOOS == "windows" { + out, err := exec.Command("cmd", "/C", "wmic bios get serialnumber").Output() + if err != nil { + return "", fmt.Errorf("failed to get bios sn: %v", err) + } + str := string(out) + lines := strings.Split(str, "\r\n") + if len(lines) > 2 { + // 获取第二行 + sn = strings.TrimSpace(lines[1]) + } + } else { + out, err := exec.Command("cat", "/sys/class/dmi/id/product_serial").Output() + if err != nil { + return "", fmt.Errorf("failed to get bios sn: %v", err) + } + sn = strings.TrimSpace(string(out)) + } + return sn, nil +} + func GlobalLabels() map[string]string { ret := make(map[string]string) for k, v := range Config.Global.Labels { @@ -311,6 +343,7 @@ func GlobalLabels() map[string]string { func Expand(nv string) string { nv = strings.Replace(nv, "$hostname", Config.GetHostname(), -1) nv = strings.Replace(nv, "$ip", Config.GetHostIP(), -1) + nv = strings.Replace(nv, "$sn", Config.GetHostSN(), -1) nv = os.Expand(nv, GetEnv) return nv } diff --git a/config/hostname.go b/config/hostname.go index b3e6891c..f9a151c9 100644 --- a/config/hostname.go +++ b/config/hostname.go @@ -11,6 +11,7 @@ import ( type HostInfoCache struct { name string ip string + sn string sync.RWMutex } @@ -30,6 +31,13 @@ func (c *HostInfoCache) GetIP() string { return ip } +func (c *HostInfoCache) GetSN() string { + c.RLock() + defer c.RUnlock() + sn := c.sn + return sn +} + func (c *HostInfoCache) SetHostname(name string) { if name == c.GetHostname() { return @@ -50,6 +58,16 @@ func (c *HostInfoCache) SetIP(ip string) { c.Unlock() } +func (c *HostInfoCache) SetSN(sn string) { + if sn == c.GetSN() { + return + } + + c.Lock() + c.sn = sn + c.Unlock() +} + func InitHostInfo() error { hostname, err := os.Hostname() if err != nil { @@ -64,10 +82,15 @@ func InitHostInfo() error { } ip = fmt.Sprint(nip) } - + var sn string + sn, err = GetBiosSn() + if err != nil { + return err + } HostInfo = &HostInfoCache{ name: hostname, ip: fmt.Sprint(ip), + sn: sn, } go HostInfo.update() @@ -90,5 +113,11 @@ func (c *HostInfoCache) update() { } else { HostInfo.SetIP(fmt.Sprint(ip)) } + sn, err := GetBiosSn() + if err != nil { + log.Println("E! failed to get sn:", err) + } else { + HostInfo.SetSN(sn) + } } }