github.com/zooyer/miskit@v1.0.71/device/device.go (about)

     1  /**
     2   * @Author: zzy
     3   * @Email: zhangzhongyuan@didiglobal.com
     4   * @Description:
     5   * @File: device.go
     6   * @Package: device
     7   * @Version: 1.0.0
     8   * @Date: 2022/10/4 14:05
     9   */
    10  
    11  package device
    12  
    13  import (
    14  	"fmt"
    15  	"net"
    16  	"os/exec"
    17  	"runtime"
    18  	"sort"
    19  	"strings"
    20  
    21  	"github.com/yumaojun03/dmidecode"
    22  	"github.com/zooyer/embed/log"
    23  )
    24  
    25  func containsAny(value string, any ...string) bool {
    26  	for _, v := range any {
    27  		if strings.Contains(value, v) {
    28  			return true
    29  		}
    30  	}
    31  
    32  	return false
    33  }
    34  
    35  func execCommand(name string, arg ...string) (output string, err error) {
    36  	out, err := exec.Command(name, arg...).CombinedOutput()
    37  	if err != nil {
    38  		return
    39  	}
    40  
    41  	return string(out), nil
    42  }
    43  
    44  func wmicByKey(t, key string) string {
    45  	output, err := execCommand("wmic", t, "get", key)
    46  	if err != nil {
    47  		log.ZError("wmicByKey execCommand error:", err.Error())
    48  		return ""
    49  	}
    50  
    51  	// 去掉前缀
    52  	output = strings.TrimSpace(output)
    53  	output = strings.TrimPrefix(output, key)
    54  	output = strings.TrimSpace(output)
    55  
    56  	// 多个结果以\n分隔
    57  	lines := strings.Split(output, "\n")
    58  	outs := make([]string, 0, len(lines))
    59  	for _, line := range lines {
    60  		if line = strings.TrimSpace(line); line == "" {
    61  			continue
    62  		}
    63  		outs = append(outs, line)
    64  	}
    65  	output = strings.Join(outs, "\n")
    66  
    67  	// 去掉无效值
    68  	output = strings.TrimPrefix(output, "None")
    69  	output = strings.TrimPrefix(output, "Default string")
    70  
    71  	return output
    72  }
    73  
    74  func dmiDecode(t string) map[string]string {
    75  	output, err := execCommand("dmidecode", "-q", "-t", t)
    76  	if err != nil {
    77  		log.ZError("dmiDecode execCommand error:", err.Error())
    78  		return nil
    79  	}
    80  
    81  	var info = make(map[string]string)
    82  	lines := strings.Split(output, "\n")
    83  	if len(lines) > 0 {
    84  		lines = lines[1:]
    85  	}
    86  
    87  	for _, line := range lines {
    88  		if line = strings.TrimSpace(line); line == "" {
    89  			continue
    90  		}
    91  
    92  		fields := strings.Split(line, ":")
    93  		if len(fields) != 2 {
    94  			continue
    95  		}
    96  
    97  		name := strings.TrimSpace(fields[0])
    98  		value := strings.TrimSpace(fields[1])
    99  		if name == "" {
   100  			continue
   101  		}
   102  
   103  		info[name] = value
   104  	}
   105  
   106  	return info
   107  }
   108  
   109  func dmiDecodeByKey(t, key string) string {
   110  	return dmiDecode(t)[key]
   111  }
   112  
   113  func getMacAddress() (addr []string, err error) {
   114  	interfaces, err := net.Interfaces()
   115  	if err != nil {
   116  		return
   117  	}
   118  
   119  	defer sort.Strings(addr)
   120  
   121  	for _, i := range interfaces {
   122  		is, err := isPhysicalEthernet(i.Index)
   123  		if err != nil {
   124  			return nil, err
   125  		}
   126  
   127  		if !is || i.Flags&net.FlagLoopback != 0 {
   128  			continue
   129  		}
   130  
   131  		addr = append(addr, fmt.Sprintf("%s", i.HardwareAddr.String()))
   132  
   133  		//switch runtime.GOOS {
   134  		//case "windows":
   135  		//case "darwin":
   136  		//	fallthrough
   137  		//case "linux":
   138  		//	if !containsAny(i.Name, "en", "eno", "ens", "enp2s", "eth") {
   139  		//		continue
   140  		//	}
   141  		//
   142  		//	if containsAny(i.Name, "bridge", "vmenet", "utun") {
   143  		//		continue
   144  		//	}
   145  		//}
   146  	}
   147  
   148  	return
   149  }
   150  
   151  func getBaseboardIDByWindows() string {
   152  	return wmicByKey("baseboard", "SerialNumber")
   153  }
   154  
   155  func getBaseboardIDByDarwin() []string {
   156  	return nil
   157  	panic("implement")
   158  }
   159  
   160  func getBaseboardIDByLinux() string {
   161  	return dmiDecodeByKey("2", "Serial Number")
   162  }
   163  
   164  func getBiosSNByWindows() string {
   165  	return strings.ReplaceAll(wmicByKey("bios", "SerialNumber"), " ", "")
   166  }
   167  
   168  func getBiosSNByDarwin() []string {
   169  	output, err := execCommand("system_profiler", "SPHardwareDataType")
   170  	if err != nil {
   171  		log.ZError("getBiosSNByDarwin execCommand error:", err.Error())
   172  		return nil
   173  	}
   174  
   175  	var sn []string
   176  	for _, line := range strings.Split(output, "\n") {
   177  		if strings.Contains(line, "Serial Number (system)") && strings.Contains(line, ":") {
   178  			sn = append(sn, strings.TrimSpace(strings.Split(line, ":")[1]))
   179  		}
   180  	}
   181  
   182  	return sn
   183  }
   184  
   185  func getBiosSNByLinux() string {
   186  	return strings.ReplaceAll(dmiDecodeByKey("1", "Serial Number"), "System Serial Number", "")
   187  }
   188  
   189  func getCPUIDByWindows() []string {
   190  	return strings.Split(wmicByKey("cpu", "ProcessorId"), "\n")
   191  }
   192  
   193  func getCPUIDByDarwin() []string {
   194  	return nil
   195  	panic("implement")
   196  }
   197  
   198  func getCPUIDByLinux() []string {
   199  	return strings.Split(dmiDecodeByKey("4", "ID"), " ")
   200  }
   201  
   202  func getOSUUIDByWindows() string {
   203  	return wmicByKey("csproduct", "UUID")
   204  }
   205  
   206  func getOSUUIDByDarwin() []string {
   207  	return nil
   208  	panic("implement")
   209  }
   210  
   211  func getOSUUIDByLinux() string {
   212  	output, err := execCommand("dmidecode", "-s", "system-uuid")
   213  	if err != nil {
   214  		log.ZError("getOSUUIDByLinux execCommand error:", err.Error())
   215  		return ""
   216  	}
   217  
   218  	output = strings.TrimSpace(output)
   219  
   220  	return output
   221  }
   222  
   223  func BaseboardSN() []string {
   224  	switch runtime.GOOS {
   225  	case "darwin":
   226  		return getBaseboardIDByDarwin()
   227  	case "linux":
   228  		return []string{getBaseboardIDByLinux()}
   229  	case "windows":
   230  		return []string{getBaseboardIDByWindows()}
   231  		dmi, err := dmidecode.New()
   232  		if err != nil {
   233  			return nil
   234  		}
   235  
   236  		boards, err := dmi.BaseBoard()
   237  		if err != nil {
   238  			return nil
   239  		}
   240  
   241  		var sn = make([]string, 0, len(boards))
   242  		for _, board := range boards {
   243  			sn = append(sn, fmt.Sprintf("%s %s", board.Manufacturer, board.SerialNumber))
   244  		}
   245  
   246  		return sn
   247  	}
   248  
   249  	return nil
   250  }
   251  
   252  func BiosSN() []string {
   253  	switch runtime.GOOS {
   254  	case "darwin":
   255  		return getBiosSNByDarwin()
   256  	case "linux":
   257  		return []string{getBiosSNByLinux()}
   258  	case "windows":
   259  		return []string{getBiosSNByWindows()}
   260  		dmi, err := dmidecode.New()
   261  		if err != nil {
   262  			return nil
   263  		}
   264  
   265  		bios, err := dmi.BIOS()
   266  		if err != nil {
   267  			return nil
   268  		}
   269  
   270  		var sn = make([]string, len(bios))
   271  		for _, b := range bios {
   272  			sn = append(sn, fmt.Sprintf("%s %s %v", strings.TrimSpace(b.Vendor), strings.TrimSpace(b.BIOSVersion), b.Characteristics))
   273  		}
   274  
   275  		return sn
   276  	}
   277  
   278  	return nil
   279  }
   280  
   281  func ProcessorSN() []string {
   282  	switch runtime.GOOS {
   283  	case "darwin":
   284  		return getCPUIDByDarwin()
   285  	case "linux":
   286  		return getCPUIDByLinux()
   287  	case "windows":
   288  		return getCPUIDByWindows()
   289  		dmi, err := dmidecode.New()
   290  		if err != nil {
   291  			return nil
   292  		}
   293  
   294  		processor, err := dmi.Processor()
   295  		if err != nil {
   296  			return nil
   297  		}
   298  
   299  		var id = make([]string, 0, len(processor))
   300  		for _, p := range processor {
   301  			id = append(id, fmt.Sprintf("%s %s", strings.TrimSpace(p.Version), p.ID))
   302  		}
   303  
   304  		return id
   305  	}
   306  
   307  	return nil
   308  }
   309  
   310  func MAC() []string {
   311  	addr, _ := getMacAddress()
   312  	return addr
   313  }
   314  
   315  func SystemID() []string {
   316  	switch runtime.GOOS {
   317  	case "darwin":
   318  		return getOSUUIDByDarwin()
   319  	case "linux":
   320  		return []string{getOSUUIDByLinux()}
   321  	case "windows":
   322  		return []string{getOSUUIDByWindows()}
   323  		dmi, err := dmidecode.New()
   324  		if err != nil {
   325  			return nil
   326  		}
   327  
   328  		system, err := dmi.System()
   329  		if err != nil {
   330  			return nil
   331  		}
   332  
   333  		var id = make([]string, 0, len(system))
   334  		for _, s := range system {
   335  			id = append(id, fmt.Sprintf("%s %s %s", s.Manufacturer, s.ProductName, s.SerialNumber))
   336  		}
   337  
   338  		return id
   339  	}
   340  
   341  	return nil
   342  }