Python 提取Linux的硬體資訊
1、程式碼實現目的
注:程式碼可以直接貼上使用
為了實現對主機的整體有明確的瞭解,實現了下面的程式碼功能
程式碼主要功能是:
提取到主機的記憶體、硬碟、CPU、型號等資訊
插入到mysql的資料庫中
回到頂部
2、程式碼具體實現步驟
2.1首先要先在mysql中新建資料庫和資料表
新建資料庫:
create database host;
新建資料表:
CREATE TABLE `host_data` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`product` varchar(255) DEFAULT NULL,
`cpu_num` varchar(255) DEFAULT NULL,
`hostname` varchar(255) DEFAULT NULL,
`ip_out` varchar(255) NOT NULL DEFAULT '',
`cpu_model` varchar(255) DEFAULT NULL,
`ip_in` varchar(255) DEFAULT NULL,
`osver` varchar(255) DEFAULT NULL,
`sn` varchar(255) DEFAULT NULL,
`Memory` varchar(255) DEFAULT NULL,
`vender` varchar(255) DEFAULT NULL,
`Disk` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`,`ip_out`),
UNIQUE KEY `ip_out` (`ip_out`)
) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8;
2.2 下面就是具體獲取硬體資訊的程式碼:
#!/usr/bin/env python
# encoding: utf-8
'''
收集主機的資訊:
主機名稱、IP、系統版本、伺服器廠商、型號、序列號、CPU資訊、記憶體資訊
'''
from subprocess import Popen, PIPE
import os, sys
import socket, fcntl, struct
from collections import namedtuple
import pymysql
import re
'''獲取所以磁碟資訊'''
disk_ntuple = namedtuple('partition', 'device mountpoint fstype')
usage_ntuple = namedtuple('usage', 'total used free percent')
''' 獲取 ifconfig 命令的輸出 '''
def getIfconfig():
p = Popen(['ifconfig'], stdout=PIPE)
data = p.stdout.read()
return data
''' 獲取 dmidecode 命令的輸出 '''
def getDmi():
p = Popen(['dmidecode'], stdout=PIPE)
data = p.stdout.read()
return data
'''獲取磁碟總大小 格式sda[300GB]+sdb[300GB]'''
def humanize_bytes(bytesize, precision=0):
abbrevs = (
(10**15, 'PB'),
(10**12, 'TB'),
(10**9, 'GB'),
(10**6, 'MB'),
(10**3, 'kB'),
(1, 'bytes')
)
if bytesize == 1:
return '1 byte'
for factor, suffix in abbrevs:
if bytesize >= factor:
break
return '%.*f%s' % (precision, round(float(bytesize) / factor), suffix)
def dev_phy_size():
with open('/proc/partitions','r') as dp:
res = ''
for disk in dp.readlines():
if re.search(r'[s,h,v]d[a-z]\n',disk):
blknum = disk.strip().split(' ')[-2]
dev = disk.strip().split(' ')[-1]
size = int(blknum)*1024
consist = dev+'['+humanize_bytes(size).strip()+']'
res += consist + '+'
return {'Disk':res[:-1]}
# '''獲取分割槽路徑和掛載、格式資訊'''
# def disk_partitions(all=False):
# """Return all mountd partitions as a nameduple.
# If all == False return phyisical partitions only.
# """
# phydevs = []
# f = open("/proc/filesystems", "r")
# for line in f:
# if not line.startswith("nodev"):
# phydevs.append(line.strip())
#
# retlist = []
# f = open('/etc/mtab', "r")
# for line in f:
# if not all and line.startswith('none'):
# continue
# fields = line.split()
# device = fields[0]
# mountpoint = fields[1]
# fstype = fields[2]
# if not all and fstype not in phydevs:
# continue
# if device == 'none':
# device = ''
# ntuple = disk_ntuple(device, mountpoint, fstype)
# retlist.append(ntuple)
# return retlist
#
#
#
# '''獲取磁碟的使用情況(總、已用、可用、百分比)'''
# def disk_usage(path):
# """Return disk usage associated with path."""
# hd = {}
# st = os.statvfs(path)
# free = (st.f_bavail * st.f_frsize)
# total = (st.f_blocks * st.f_frsize)
# used = (st.f_blocks - st.f_bfree) * st.f_frsize
# try:
# percent = ret = (float(used) / total) * 100
# except ZeroDivisionError:
# percent = 0
# hd['total'] = total
# hd['used'] = used
# hd['free'] = free
# hd['percent'] = round(percent, 1)
# return hd
#
#
# def access_disk():
# hd = {}
# disks = disk_partitions()
# for i in disks:
# d = list(i)[1]
# a_disks = disk_usage(d)
# hd["cipan"] = a_disks
# return hd
''' 根據空行分段落 返回段落列表'''
def parseData(data):
parsed_data = []
new_line = ''
data = [i for i in data.split('\n') if i]
for line in data:
if line[0].strip():
parsed_data.append(new_line)
new_line = line + '\n'
else:
new_line += line + '\n'
parsed_data.append(new_line)
return [i for i in parsed_data if i]
''' 根據輸入的段落資料分析出ifconfig的每個網絡卡ip資訊 '''
'''外網IP'''
def parseIfconfig_out(ifname):
dic = {}
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
ipaddr = socket.inet_ntoa(fcntl.ioctl(s.fileno(), 0x8915, struct.pack('256s', ifname[:15]))[20:24])
dic['ip_out'] = ipaddr
return dic
'''內網IP'''
def parseIfconfig_in(ifname):
dic = {}
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
ipaddr = socket.inet_ntoa(fcntl.ioctl(s.fileno(), 0x8915, struct.pack('256s', ifname[:15]))[20:24])
dic['ip_in'] = ipaddr
return dic
''' 根據輸入的dmi段落資料 分析出指定引數 '''
def parseDmi(parsed_data):
dic = {}
parsed_data = [i for i in parsed_data if i.startswith('System Information')]
parsed_data = [i for i in parsed_data[0].split('\n')[1:] if i]
dmi_dic = dict([i.strip().split(':') for i in parsed_data])
dic['vender'] = dmi_dic['Manufacturer'].strip()
dic['product'] = dmi_dic['Product Name'].strip()
dic['sn'] = dmi_dic['Serial Number'].strip()
return dic
''' 獲取Linux系統主機名稱 '''
def getHostname():
p = Popen(['hostname'], stdout=PIPE)
data = p.stdout.read().split('\n')[0]
return {'hostname': data}
''' 獲取Linux系統的版本資訊 '''
def getOsVersion():
with open('/etc/issue') as fd:
for line in fd:
osver = line.strip()
break
return {'osver': osver}
''' 獲取CPU的型號和CPU的核心數 '''
def getCpu():
num = 0
with open('/proc/cpuinfo') as fd:
for line in fd:
if line.startswith('processor'):
num += 1
if line.startswith('model name'):
cpu_model = line.split(':')[1].strip().split()
cpu_model = cpu_model[0] + ' ' + cpu_model[2] + ' ' + cpu_model[-1]
return {'cpu_num': num, 'cpu_model': cpu_model}
''' 獲取Linux系統的總實體記憶體 '''
def getMemory():
with open('/proc/meminfo') as fd:
for line in fd:
if line.startswith('MemTotal'):
mem = int(line.split()[1].strip())
break
mem = '%.f' % (mem / 1024000.0) + ' GB'
return {'Memory': mem}
def main():
dic = {}
data_ip = getIfconfig()
parsed_data_ip = parseData(data_ip)
ip_out = parseIfconfig_out(sys.argv[1])
ip_in = parseIfconfig_in(sys.argv[2])
data_dmi = getDmi()
parsed_data_dmi = parseData(data_dmi)
dmi = parseDmi(parsed_data_dmi)
acc_disks = dev_phy_size()
# print acc_disks
hostname = getHostname()
osver = getOsVersion()
cpu = getCpu()
mem = getMemory()
dic.update(ip_in)
dic.update(ip_out)
dic.update(dmi)
dic.update(hostname)
dic.update(osver)
dic.update(cpu)
dic.update(mem)
dic.update(acc_disks)
return dic
def db_connect():
conn = pymysql.connect(host="x.x.x.x",
db='xxxxx',
user="root",
passwd="*******",
charset="utf8")
cur = conn.cursor()
return conn,cur
def save_mysql(conn, cur, dic):
k = dic.keys()
v = dic.values()
key = ",".join(k)
vs = list()
for i in v:
vs.append("'%s'" % i)
values = ",".join(vs)
# print values, k
try:
# sql = "REPLACE INTO host_data(%s) VALUES(%s)" % (key, values)
sql = "INSERT INTO host_data(%s) VALUES(%s)" % (key, values)
# print sql
cur.execute(sql)
conn.commit()
except Exception as e:
# print Exception, ": ", e
conn.rollback()
if __name__ == '__main__':
conn, cur = db_connect()
dic_data = main()
save_mysql(conn, cur, dic_data)
注:
- 指令碼需要修改 db_connect() 函式的資料庫資訊 (db引數是資料庫的庫名)
- 執行方式:python 指令碼名稱 外網網絡卡名稱 內網網絡卡名稱(因為每臺機器的網絡卡名稱不一樣,所以在執行指令碼的時候最好的把內外網的網絡卡名稱以傳值的形式給到指令碼)
- 比如: python host.py eth1 eth0