最近在使用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信息的时候就可以正常访问了。