golang判断当前主机是物理机还是虚拟机

windows下命令行获取:

1
wmic path Win32_ComputerSystem get Model

linux下命令行获取:

1
dmidecode | egrep -i 'system-product-name|product|domU'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
func isVirtualMachine() (bool, error) {
model := ""
var cmd *exec.Cmd

if runtime.GOOS == "windows" {
cmd = exec.Command("cmd", "/C", "wmic path Win32_ComputerSystem get Model")
} else { // linux
cmd = exec.Command("/bin/bash", "-c", "dmidecode | egrep -i 'system-product-name|product|domU'")
}

stdout, err := cmd.Output()

if err != nil {
return false, err
}
model = string(stdout)

if strings.Contains(model, "VirtualBox") || strings.Contains(model, "Virtual Machine") || strings.Contains(model, "VMware Virtual Platform") ||
strings.Contains(model, "KVM") || strings.Contains(model, "Bochs") || strings.Contains(model, "HVM domU") {
return true, nil
}

return false, nil
}

如果使用夜莺n9e需要更改代码

将 agent.yml中 cate 改为 auto,同时agent/report/report.go 更改如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
func report() error {
name, err := os.Hostname()
if err != nil {
return fmt.Errorf("cannot get hostname: %s", err)
}

fields, err := gatherFields(config.Config.Report.Fields)
if err != nil {
return err
}

//这里考虑区分物理机还是虚拟机, 当类型是auto 时, 判断处理
var hostCategory string
if config.Config.Report.Cate == "auto" {
isVM, _ := utils.IsVirtualMachine()
if isVM {
hostCategory ="virtual"
}else{
hostCategory ="physical"
}
logger.Debugf("ident: %s , category: %s", ident,hostCategory)
}

form := hostRegisterForm{
SN: sn,
IP: ip,
Ident: ident,
Name: name,
Cate: hostCategory, //config.Config.Report.Cate
UniqKey: config.Config.Report.UniqKey,
Fields: fields,
}

content := form.SN + form.IP + form.Ident + form.Name + form.Cate + form.UniqKey
var keys []string
for key := range fields {
keys = append(keys, key, fields[key])
}
sort.Strings(keys)

for _, key := range keys {
content += fields[key]
}

form.Digest = str.MD5(content)

servers := address.GetHTTPAddresses("ams")
for _, i := range rand.Perm(len(servers)) {
url := fmt.Sprintf("http://%s/v1/ams-ce/hosts/register", servers[i])

logger.Debugf("report: %+v", form)

var body errRes
err := httplib.Post(url).JSONBodyQuiet(form).Header("X-Srv-Token", config.Config.Report.Token).SetTimeout(time.Second * 5).ToJSON(&body)
if err != nil {
js, _ := json.Marshal(form)
logger.Errorf("report payload: %s, token: %s", string(js), config.Config.Report.Token)
return fmt.Errorf("curl %s fail: %v", url, err)
}

if body.Err != "" {
return fmt.Errorf(body.Err)
}

return nil
}

return fmt.Errorf("all server instance is dead")
}