10. 获取服务器基础信息

2020-04-03  本文已影响0人  运维开发_西瓜甜

本文链接:https://www.jianshu.com/p/b283f12193a9
作者:西瓜甜

一、 subprocess 执行本机命令

subprocessgetoutput() 方法可以接收一个字符串的参数,这个参数会被认为是当前操作系统的命令去执行,并返回字符串类型的命令执行结果,假设命令出错,会返回相应的错误信息。

比如我们执行一条命令,来获取的厂商机器信息
目标是得到这些信息

  • 厂商 就是 Manufacturer 对应的值 比如 Del
  • 服务器型号(名字) 就是 Product Name 对应的值 比如 Del R710
  • 服务器序列号 就是 Serial Number 对应的值
[root@qfedu.com ~]# rpm -q dmidecode
dmidecode-3.1-2.el7.x86_64
[root@qfedu.com ~]# dmidecode -q -t 1 2>/dev/null
System Information
    Manufacturer: Alibaba Cloud
    Product Name: Alibaba Cloud ECS
    Version: pc-i440fx-2.1
    Serial Number: 0f7e3d86-7742-4612-9f93-e3a9e4754157
    UUID: 0f7e3d86-7742-4612-9f93-e3a9e4754157
    Wake-up Type: Power Switch
    SKU Number: Not Specified
    Family: Not Specified

在 python 中可以这样做

In [1]: import subprocess

In [2]: prod_info = "dmidecode -q -t 1 2>/dev/null"

In [3]: prod_info
Out[3]: 'dmidecode -q -t 1 2>/dev/null'

In [4]: subprocess.getoutput(prod_info)
Out[4]: 'System Information\n\tManufacturer: Alibaba Cloud\n\tProduct Name: Alibaba Cloud ECS\n\tVersion: pc-i440fx-2.1\n\tSerial Number: 0f7e3d86-7742-4612-9f93-e3a9e4754157\n\tUUID: 0f7e3d86-7742-4612-9f93-e3a9e4754157\n\tWake-up Type: Power Switch\n\tSKU Number: Not Specified\n\tFamily: Not Specified\n'

In [5]:

可以看到输出结果是一个整体的字符串,和 shell 中输出的少有不同,就是这里每一行后面都有一个换行符 '\n'
那我们要想对每一行进行处理,可以使用 split('\n') 进行分割,当然我们这里使用另一个方法 splitlines(), 它默认使用的分隔符就是换行符

In [5]: ret = subprocess.getoutput(prod_info)

In [6]: ret.splitlines()
Out[6]:
['System Information',
 '\tManufacturer: Alibaba Cloud',
 '\tProduct Name: Alibaba Cloud ECS',
 '\tVersion: pc-i440fx-2.1',
 '\tSerial Number: 0f7e3d86-7742-4612-9f93-e3a9e4754157',
 '\tUUID: 0f7e3d86-7742-4612-9f93-e3a9e4754157',
 '\tWake-up Type: Power Switch',
 '\tSKU Number: Not Specified',
 '\tFamily: Not Specified']

In [7]:

那接着我们即可以循环列表中的每个元素(也就是每行),在循环中处理每行内容,得到我们想要的数据

In [7]: for line in ret.splitlines():
   ...:     print(line)
   ...:
System Information
    Manufacturer: Alibaba Cloud
    Product Name: Alibaba Cloud ECS
    Version: pc-i440fx-2.1
    Serial Number: 0f7e3d86-7742-4612-9f93-e3a9e4754157
    UUID: 0f7e3d86-7742-4612-9f93-e3a9e4754157
    Wake-up Type: Power Switch
    SKU Number: Not Specified
    Family: Not Specified

In [8]: for line in ret.splitlines():
   ...:     if 'Manufacturer:' in line:
   ...:         print(line)
   ...:
    Manufacturer: Alibaba Cloud

可以看到我们拿到了我们需要的第一个数据,并且可以进行进一步的处理,比如转换成一个字典,其他可以如法炮制。

In [12]: for line in ret.splitlines():
    ...:     if 'Manufacturer:' in line:
    ...:         k, v = line.split(": ")
    ...:         k = k.lower()
    ...:     elif 'Product Name:' in line:
    ...:         k, v = line.split(": ")
    ...:         k = k.lower().replace(' ', '_')
    ...:     elif 'Serial Number:' in line:
    ...:         k, v = line.split(": ")
    ...:         k = k.lower().replace(' ', '_')
    ...:     prod_info[k] = v
    ...:

In [13]: prod_info
Out[13]:
{'\tserial_number': '0f7e3d86-7742-4612-9f93-e3a9e4754157',
 '\tmanufacturer': 'Alibaba Cloud',
 '\tproduct_name': 'Alibaba Cloud ECS'}

和我们的目标越来接近了,但你好发现有问题

  1. 多个判断语句导致代码臃肿
  2. 并且后面那两个 elif 中有重复的代码
  3. key 中有个 Tab 键

那继续优化,思路是可以提前定义一个映射的字典

# 存放厂商和产品信息
prod_info = {}

# 定义映射字典
map_dic = {
    "Manufacturer": "manufacturer",
    "Product Name": "pod_name",
    "Serial Number": "sn"
}
for line in li:
    # 去除每行两端的空白字符
    line = line.strip()
    
    # 异常处理
    try:
        k, v = line.split(': ')

        # 判断 k 是否在字典 map_dic 的 keys 中
        if k in map_dic:

            # 获取到字典的 map_dic 中对应的 值作为 字典 prod_info 的 key
            prod_info[map_dic[k]] = v
    except ValueError as  e:
        pass

print(prod_info)
{'manufacturer': 'Alibaba Cloud',
 'pod_name': 'Alibaba Cloud ECS',
 'sn': '0f7e3d86-7742-4612-9f93-e3a9e4754157'}

二、 获取服务器的硬件基础信息

1. 基础信息

# 主机名
cmd_machine = 'uname -n'

# 内核版本
cmd_kernel = 'uname -r'

# 操作系统
cmd_os_version = "cat /etc/redhat-release || cat /etc/issue"

2. 厂家和产品信息

[root@qfedu.com]# dmidecode -q -t 1 2>/dev/null
System Information
    Manufacturer: Alibaba Cloud                   # 厂商
    Product Name: Alibaba Cloud ECS         #  机器型号
    Version: pc-i440fx-2.1
    Serial Number: 0f7e3d86-7742-4612-9f93-e3a9e4754157    # 序列号
    UUID: 0f7e3d86-7742-4612-9f93-e3a9e4754157
    Wake-up Type: Power Switch
    SKU Number: Not Specified
    Family: Not Specified

3. CPU 信息

3.1 查看物理CPU型号

grep 'model name' /proc/cpuinfo | uniq 
In [1]: import subprocess

In [2]: cmd_cpu_name = "grep 'model name' /proc/cpuinfo | uniq"

In [3]: subprocess.getoutput(cmd_cpu_name)
Out[3]: 'model name\t: Intel(R) Xeon(R) Platinum 8163 CPU @ 2.50GHz'

In [4]: cpu_name = subprocess.getoutput(cmd_cpu_name).split(": ")[1]

In [5]: cpu_name
Out[5]: 'Intel(R) Xeon(R) Platinum 8163 CPU @ 2.50GHz'

In [6]: cpu = {"cpu_name": cpu_name}

In [7]: cpu
Out[7]: {'cpu_name': 'Intel(R) Xeon(R) Platinum 8163 CPU @ 2.50GHz'}

In [8]:

3.2 获取 CPU 核心数

这里获取的 CPU 核心数是服务器 CPU 总核心数,不区分几颗物理 CPU 和每颗 CPU 的有几个核心

grep 'model name' /proc/cpuinfo | wc -l

真正管理企业资产的时候,我们都会分别统计服务器有几颗物理 CPU,每颗 CPU 有几个核心。下面就是获取这两个数据的具体实现。

3.3 查看物理CPU颗数

grep 'physical id' /proc/cpuinfo | sort -u | wc -l
In [8]: cmd_cpu_pyc = "grep 'physical id' /proc/cpuinfo | sort -u | wc -l"

In [9]: subprocess.getoutput(cmd_cpu_pyc)
Out[9]: '1'

In [10]: cpu["pyc"] = int(subprocess.getoutput(cmd_cpu_pyc))

In [11]: cpu
Out[11]: {'cpu_name': 'Intel(R) Xeon(R) Platinum 8163 CPU @ 2.50GHz', 'cpu_pyc': 1}

In [12]:

3.4 查看每颗物理 CPU 的核心数

grep 'cpu cores' /proc/cpuinfo | uniq   # 每颗 CPU 的核心数,不是总核心数
In [13]: subprocess.getoutput("grep 'cpu cores' /proc/cpuinfo | uniq")
Out[13]: 'cpu cores\t: 1'

In [14]: cpu_cores_each = subprocess.getoutput("grep 'cpu cores' /proc/cpuinfo | uniq")

In [15]: cpu_cores_each = int(cpu_cores_each.split(": ")[1])

In [16]: cpu_cores_each
Out[16]: 1

In [17]: cpu["cores_each"] = cpu_cores_each

In [18]: cpu
Out[18]:
{'cpu_name': 'Intel(R) Xeon(R) Platinum 8163 CPU @ 2.50GHz',
 'cpu_num': 1,
 'cpu_cores_each': 1}

In [19]:

4. 内存信息

[root@qfedu.com]# dmidecode -q -t 17 2>/dev/null
Memory Device
    Total Width: Unknown
    Data Width: Unknown
    Size: 4096 MB             # 容量
    Form Factor: DIMM
    Set: None
    Locator: DIMM 0          # 插槽号
    Bank Locator: Not Specified
    Type: RAM                    # 类型  物理的有 DDR3 DDR4
    Type Detail: Other
    Speed: Unknown           # 速率  物理的有 1333 等
    Manufacturer: Alibaba Cloud
    Serial Number: Not Specified
    Asset Tag: Not Specified
    Part Number: Not Specified
    Rank: Unknown
    Configured Clock Speed: Unknown
    Minimum Voltage: Unknown
    Maximum Voltage: Unknown
    Configured Voltage: Unknown
Memory Device
    Total Width: 72 bits
    Data Width: 64 bits
    Size: 8192 MB
    Form Factor: DIMM
    Set: 6
    Locator: DIMM_B2
    Bank Locator: Not Specified
    Type: DDR3
    Type Detail: Synchronous Registered (Buffered)
    Speed: 1333 MT/s
    Manufacturer: 00CE00B380CE
    Serial Number: 82B79F71
    Asset Tag: 02120363
    Part Number: M393B1K70DH0-YH9
    Rank: 2
Memory Device
    Total Width: 72 bits
    Data Width: 64 bits
    Size: 8192 MB
    Form Factor: DIMM
    Set: 6
    Locator: DIMM_B3
    Bank Locator: Not Specified
    Type: DDR3
    Type Detail: Synchronous Registered (Buffered)
    Speed: 1333 MT/s
    Manufacturer: 00CE00B380CE
    Serial Number: 32CDDE81
    Asset Tag: 02120361
    Part Number: M393B1K70CH0-YH9
    Rank: 2
Memory Device
    Total Width: 72 bits
    Data Width: 64 bits
    Size: No Module Installed
    Form Factor: DIMM
    Set: 4
    Locator: DIMM_B4
    Bank Locator: Not Specified
    Type: DDR3
    Type Detail: Synchronous
    Speed: Unknown
    Manufacturer:
    Serial Number:
    Asset Tag:
    Part Number:
    Rank: Unknown
Memory Device
    Total Width: 72 bits
    Data Width: 64 bits
    Size: 8192 MB
    Form Factor: DIMM
    Set: 5
    Locator: DIMM_B5
    Bank Locator: Not Specified
    Type: DDR3
    Type Detail: Synchronous Registered (Buffered)
    Speed: 1333 MT/s
    Manufacturer: 00CE04B380CE
    Serial Number: 85966B82
    Asset Tag: 02113621
    Part Number: M393B1K70DH0-YH9
    Rank: 2
Memory Device
    Total Width: 72 bits
    Data Width: 64 bits
    Size: 8192 MB
    Form Factor: DIMM
    Set: 6
    Locator: DIMM_B6
    Bank Locator: Not Specified
    Type: DDR3
    Type Detail: Synchronous Registered (Buffered)
    Speed: 1333 MT/s
    Manufacturer: 000000B380CE
    Serial Number: 00000000
    Asset Tag: 02121563
    Part Number:
    Rank: 2

作业

请使用以上信息,编写一个脚本,输出如下信息

{
    "base_info": {
        "host_name": "db_server",
        "kernel": "3.10.0-957.21.3.el7.x86_64",
        "os": "CentOS Linux release 7.6.1810 (Core)",
        'manufacturer': 'Alibaba Cloud',
        'pod_name': 'Alibaba Cloud ECS',
        'sn': '0f7e3d86-7742-4612-9f93-e3a9e4754157'
    },
    "cpu": {
        'name': 'Intel(R) Xeon(R) Platinum 8163 CPU @ 2.50GHz',
        'num': 1,
        'cores_each': 1
    },
    "mem": [
        {
            'capacity': '8192 MB',
            'slot': 'DIMM_A3',
            'model': 'DDR3',
            'speed': '1333 MT/s',
            'manufacturer': '00CE04B380CE',
            'sn': '8362A2F8'
        },
        {
            'capacity': 'No Module Installed',
            'slot': 'DIMM_A4',
            'model': 'DDR3',
            'speed': 'Unknown'
        }
        ...........略............
    ]
}

内存源数据使用上面 R710 的,映射字典使用下面这个

key_map = {
        'Size': 'capacity',
        'Locator': 'slot',
        'Type': 'model',
        'Speed': 'speed',
        'Manufacturer': 'manufacturer',
        'Serial Number': 'sn',
}

内存处理参考代码

def parse(data):
    info_mem = []
    # 首先把服务器上的所有插槽分开,并发到一个列表中
    # 这个语法叫列表生成式, 表示循环中的元素为真时候,将 mem 添加到列表中
    memory_list = [ mem for mem in data.split('Memory Device') if mem]


    for item in memory_list:
        # 把每个插槽的信息放到一个字典中
        single_slot = {}
        
        for line in item.splitlines():
            line = line.strip()
            if len(line.split(': ')) == 2:
                key, val = line.split(': ')
                if key in key_map:
                    # 获取到映射字典的 value 作为新字典的 key
                    single_slot[key_map[key]] = val
        # 含有插槽信息的字典:
        # {'capacity': '8192 MB', 'slot': 'DIMM_A3', 'model': 'DDR3', 'speed': '1333 MT/s', 'manufacturer': '00CE04B380CE', 'sn': '8362A2F8'}
  
        info_mem.append(single_slot)
    return info_mem
上一篇下一篇

猜你喜欢

热点阅读