dmidecode的Python解析

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
解析dmidecode命令输出结果,返回JSON格式数据
测试服务器Dell VMware虚拟机
测试系统为CentOS 6.x 7.x
Python版本为Python3.6
原版参考的是 https://pypi.org/project/dmidecode/ 但是在Python3上无法直接使用而且我觉得它有些逻辑问题需要做一些修改
"""

import sys
import subprocess

__version__ = "0.1.0"
__author__ = "rex.chen"


class Dmidecode(object):
    def __init__(self):
        # 注释掉里面的键值意味着忽略某些类型
        self._DMI_TYPE = {
            0: "BIOS Information",        # BIOS信息 提供商、版本等
            1: "System Information",      # 系统信息包括服务器厂商、服务器的星号、服务器序列号
            2: "Base Board Information",
            3: "Chassis Information",     # 可以获取服务器的高度,比如1U等。
            4: "Processor Information",    # 每个逻辑CPU的信息,物理CPU数量*核心数量=逻辑CPU数量
            6: "Memory Module Information",
            7: "Cache Information",
            8: "Port Connector Information",
            9: "System Slot Information",
            10: "On Board Device Information",
            11: "OEM Strings",
            15: "System Event Log",
            16: "Physical Memory Array",
            17: "Memory Device",          # 每个内存槽位上查的内存条信息,类型、容量、主频、序列号等
            18: "32-bit Memory Error Information",
            19: "Memory Array Mapped Address",
            20: "Memory Device Mapped Address",
            23: "System Reset",
            24: "Hardware Security",
            30: "Out-of-band Remote Access",
            32: "System Boot Information",
            33: "64-bit Memory Error Information",
            38: "IPMI Device Information",
            41: "Onboard Device",
            # 126: "Inactive",
            # 127: "End Of Table"
        }

    def parse_dmi(self, content):
        """
        解析dmidecode命令输出
        :param content: 传递进来dmidecode命令执行的原始输出结果
        :return: 重新组装后的数据字典
        """
        info = {}
        try:
            """
            这里是一个关键点,dmidecode命令输出其实是层级结构的,它使用制表符	来表示层级,lines可以列表,但后续处理会比较麻烦
            所以这里使用迭代器一个是占用空间少,另外是你每一次传递lines到其他地方当调用next()或者for循环时它都是从上一次的位置
            继续向下,这样对于处理这种dmidecode输出的有层级关系的非结构化数据比较方便。
            """
            lines = iter(content.strip().splitlines())
            while True:
                try:
                    line = next(lines)
                    if line.startswith(b'Handle 0x'):
                        typ = int(str(line).split(',', 2)[1].strip()[len('DMI type'):])
                        if typ in self._DMI_TYPE:
                            if typ not in info:
                                info[self._DMI_TYPE[typ]] = []
                                info[self._DMI_TYPE[typ]].append(self._parse_handle_section(lines))
                            else:
                                info[self._DMI_TYPE[typ]].append(self._parse_handle_section(lines))
                except StopIteration:
                    break
            return info
        except Exception as err:
            print("Error occured in Function parse_dmi")
            print(err)

    def _parse_handle_section(self, lines):
        """
        解析每个type下面的信息,也就是每一个 Handle 0x 下面的信息
        :param lines: 传递所有的内容进来,也就是之前生成的迭代器,而且这个迭代器是接着上面的位置继续向后迭代
        :return: 字典,每个type下面的子信息组成的字典
        """
        data = {}
        title = str(next(lines).strip().decode(encoding='utf-8'))
        try:
            for line in lines:
                line = line.rstrip()
                strline = str(line.strip().decode(encoding='utf-8'))
                if line.startswith(b'		'):
                    data[k].append(strline)
                elif line.startswith(b'	'):
                    k, v = str(line.strip().decode(encoding='utf-8')).split(":", 1)
                    if v:
                        data[k] = v.strip()
                    else:
                        data[k] = []
                else:
                    break
        except Exception as err:
            print("Error occured in Function parse_handle_section")
            print("Data section is %s " % title)
            print(err)
        return data


def main():
    cmd = "sshpass -p 123456 ssh root@172.16.48.171 '/usr/sbin/dmidecode'"
    mydmi = Dmidecode()
    try:
        completed_process = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        if completed_process.returncode == 0:
            data = completed_process.stdout
            print(mydmi.parse_dmi(data))
        else:
            print("Returncode is not 0")
    except Exception as err:
        print(err)

if __name__ == "__main__":
    try:
        main()
    finally:
        sys.exit()

原文地址:https://www.cnblogs.com/rexcheny/p/10307523.html