最近在使用go开发后台的时候,有这么一个需求,开发的服务需要做一个license,用户需要license和服务同时在且有效的情况下才能运行服务,其实在正常情况下,也没什么,但是就是因为部署的时候客户那边可能用的是docker部署,那么如何在docker里面获取到宿主机的CPU信息就成了必须,因为license需要用到宿主机的CPU信息,也可以使用主板信息或者MAC信息等,我们这次用的是CPU序列号信息,用来做license的绑定。
我先说下我的整个流程,代码里面我先是用go语言实现了获取CPU序列号信息,使用的是linux的dmidecode命令进行的获取,命令如下
[root@dmt ~]# dmidecode -t processor | grep ID | head -1
ID: 57 06 05 00 FF FB 8B 0F
[root@dmt ~]#
下面附上我使用go来获取CPU序列号的代码,返回两个参数,第一个是CPU序列号的字符串类型数据,第二个参数是错误码数据
//获取CPUID函数
func GET_CPUID() (string, error) {
cmd := exec.Command("/bin/sh", "-c", `dmidecode -t processor | grep ID | head -1`)
stdout, err := cmd.StdoutPipe()
if err != nil {
fmt.Println("cmd.StdoutPipe: " + err.Error())
return "", err
}
stderr, err := cmd.StderrPipe()
if err != nil {
fmt.Println("cmd.StderrPipe: ", err.Error())
return "", err
}
if err := cmd.Start(); err != nil {
fmt.Println("cmd.Start: ", err.Error())
return "", err
}
bytesErr, err := ioutil.ReadAll(stderr)
if err != nil {
fmt.Println("ioutil.ReadAll stderr: ", err.Error())
return "", err
}
if len(bytesErr) != 0 {
fmt.Printf("stderr is not nil: %s", bytesErr)
return "", errors.New(string(bytesErr))
}
bytes, err := ioutil.ReadAll(stdout)
if err != nil {
fmt.Println("ioutil.ReadAll stdout: ", err.Error())
return "", err
}
if err := cmd.Wait(); err != nil {
fmt.Println("cmd.Wait: ", err.Error())
return "", err
}
cpuId := string(bytes)
cpuId = strings.Replace(cpuId, "ID: ", "", -1)
cpuId = strings.Replace(cpuId, "\t", "", -1)
cpuId = strings.Replace(cpuId, "\n", "", -1)
cpuId = strings.Replace(cpuId, " ", "-", -1)
return cpuId, err
}
license的计算逻辑此处不方便公开,差不多
然后我的整个后台服务开发完成后,如果是直接在linux主机上部署,是没有任何问题的,因为直接就可以通过dmidecode命令获取到CPU的相关信息,如果是docker部署的话,需要在docker部署的yml文件里面添加如下内容。
version: '3.4'
services:
pap:
image: DOCKER_IMAGE
volumes:
- /etc/localtime:/etc/localtime:ro
- type: bind
source: /usr/sbin/dmidecode
target: /usr/sbin/dmidecode
- type: bind
source: /dev/mem
target: /dev/mem
privileged: true
ports:
- "8000:8000"
restart:
always
其中我把自己项目相关的代码都去掉了,其实最重要的就是下面这几行,每一行的作用我在后面做了备注
- type: bind
source: /usr/sbin/dmidecode
target: /usr/sbin/dmidecode
- type: bind
source: /dev/mem
target: /dev/mem
privileged: true
然后使用添加了这些信息的yml文件部署docker的话,程序在docker里面访问CPU信息的时候就可以正常访问了。