背景介绍
在日常运维或者迁移客户系统的时候我们需要快速的了解客户应用系统的主机的一些基本信息,我们可以通过Linux的命令获得相关信息,自己信息总结,我这里收集总结了基于Python2.7的一些脚本,可以快速获得系统的基础信息。选择Python2.7是应为现在绝大多数Linux 操作系统依然使用的默认版本的Python还是2.x的版本。本身这些脚本可以下载直接运行,无需安装任何第三方的包方便使用。
获得操作系统信息
#coding=utf-8
import platform
def GetPlatformInfo():
print ("----------Operation System--------------------------")
# 获取Python版本
# print platform.python_version()
# 获取操作系统可执行程序的结构,,(’32bit’, ‘WindowsPE’)
print "操作系统可执行程序的结构: " + str(platform.architecture())
# 计算机的网络名称,’acer-PC’
print "主机名称: " + str(platform.node())
# 获取操作系统名称及版本号,’Windows-7-6.1.7601-SP1′
print "操作系统名称及版本号: " + str(platform.platform())
# 计算机处理器信息,’Intel64 Family 6 Model 42 Stepping 7, GenuineIntel’
print "CPU: " + str(platform.processor())
# 获取操作系统中Python的构建日期
# print platform.python_build()
# 获取系统中python解释器的信息
# print platform.python_compiler()
# if platform.python_branch() == "":
# print platform.python_implementation()
# print platform.python_revision()
print "操作系统版本: " + platform.release()
print "操作系统: " + platform.system()
# print platform.system_alias()
# 获取操作系统的版本
# print platform.version()
# 包含上面所有的信息汇总
# print platform.uname()
def UsePlatform():
sysstr = platform.system()
if (sysstr == "Windows"):
print ("Call Windows tasks")
elif (sysstr == "Linux"):
print ("Call Linux tasks")
else:
print sysstr
if __name__ == "__main__":
GetPlatformInfo()
输出示例:
----------Operation System--------------------------
操作系统可执行程序的结构: ('64bit', 'ELF')
主机名称: centos-7-3.shared
操作系统名称及版本号: Linux-3.10.0-693.5.2.el7.x86_64-x86_64-with-centos-7.4.1708-Core
CPU: x86_64
操作系统版本: 3.10.0-693.5.2.el7.x86_64
操作系统: Linux
获系统和磁盘挂载信息
此脚本的特点是输出信息通过不同的颜色区分
import os
import sys
import platform
import glob
import re
#####################################HOST INFORMATION
OS_flavour = platform.system()
print "\033[1;36;40mOS Flavour \033[0;37;40m : %s\n" % OS_flavour
OS_distribution = platform.linux_distribution()
print "\033[1;36;40mOS Vendor : \033[0;37;40m %s\t\033[1;36;40m Version : \033[0;37;40m %s\t\033[1;36;40mId \033[0;37;40m: %s\n" % OS_distribution
OS_arch = platform.processor()
print "\033[1;36;40mOS Architecture : \033[0;37;40m %s\n" % OS_arch
Network_hostanme = platform.node()
print "\033[1;36;40mServer\'s Network Hostname :\033[0;37;40m %s\n" % Network_hostanme
Linux_kernel = platform.uname()
print "\033[1;36;40mLinux Kernel Version : \033[0;37;40m %s\n" % Linux_kernel[2]
#######DECLARING SYSFS PATH
sysfs = ["/sys/class/scsi_device/", "/sys/class/scsi_host/", "/sys/devices/", "/sys/block/"]
#######Findins Scsi Device
scsi_device = os.listdir(sysfs[0])
pci_scsi = {}
print "\033[1;36;40mAvailable Scsi Device ID : \033[0;37;40m %s\n" % scsi_device
#######FINDING PCI
for i in scsi_device:
pci_array = os.readlink(sysfs[0] + i).rsplit("/\\")
pci_scsi[i] = pci_array[3:5]
print "\033[1;36;40mMapping OS SCSI ID TO PCI ID \033[0;37;40m"
print "\033[1;32;40m\tSCSI ID\t\tPCI ID \033[0;37;40m \n"
for n in pci_scsi:
print "\t%s\t\t%s" % (n, pci_scsi[n])
print "\n"
###Host Adapter and attached Disk information#####
scsi_host = os.listdir(sysfs[1])
print "\033[1;36;40mFounded Host adapter :\t \033[0;37;40m %s\n" % scsi_host
输出示例;
OS Flavour : Linux
OS Vendor : CentOS Linux Version : 7.4.1708 Id : Core
OS Architecture : x86_64
Server's Network Hostname : centos-7-3.shared
Linux Kernel Version : 3.10.0-693.5.2.el7.x86_64
Available Scsi Device ID : ['2:0:0:0', '3:0:0:0']
Mapping OS SCSI ID TO PCI ID
SCSI ID PCI ID
2:0:0:0 []
Founded Host adapter : ['host0', 'host1', 'host2', 'host3', 'host4', 'host5', 'host6', 'host7']
Mapping OS SCSI ID TO PCI ID
SCSI ID PCI ID
2:0:0:0 []
3:0:0:0 []
Founded Host adapter : ['host0', 'host1', 'host2', 'host3', 'host4', 'host5', 'host6', 'host7']
获取磁盘信息-分区、挂载点
#!/usr/bin/python
import os
import re
import sys
import errno
from subprocess import Popen,PIPE
def find_device(data, pciid):
id = re.escape(pciid)
m = re.search("^" + id + "\s(.*)$", data, re.MULTILINE)
return m.group(1)
def pretty_size(size):
size_strs = ['B', 'KiB', 'MiB', 'GiB', 'TiB']
last_size = size
fract_size = size
num_divs = 0
while size > 1:
fract_size = last_size
last_size = size
size /= 1024
num_divs += 1
num_divs -= 1
fraction = fract_size / 1024
pretty = "%.2f" % fraction
pretty = pretty + size_strs[num_divs]
return pretty
def virtual_device(path):
for dir in os.listdir(path):
if re.search("device", dir):
return 0
return 1
class Device:
def __init__(self):
self.sectorsize = ""
self.sectors = ""
self.rotational = ""
self.sysdir = ""
self.host = ""
self.model = ""
self.vendor = ""
self.holders = []
self.diskname = ""
self.partitions = []
self.removable = ""
self.start = ""
self.discard = ""
self.sysfs_no_links = 0
def populate_model(self):
try:
f = open(self.sysdir + "/device/model")
self.model = f.read().rstrip()
f.close()
except IOError:
# do nothing
pass
def populate_vendor(self):
try:
f = open(self.sysdir + "/device/vendor")
self.vendor = f.read().rstrip()
f.close()
except IOError:
#do nothing
pass
def populate_sectors(self):
try:
f = open(self.sysdir + "/size")
self.sectors = f.read().rstrip()
f.close()
except IOError:
self.sectors = 0
def populate_sector_size(self):
try:
f = open(self.sysdir + "/queue/hw_sector_size")
self.sectorsize = f.read().rstrip()
f.close()
except IOError:
# if this sysfs doesnt show us sectorsize then just assume 512
self.sectorsize = "512"
def populate_rotational(self):
try:
f = open(self.sysdir + "/queue/rotational")
rotation = f.read().rstrip()
f.close()
except IOError:
self.rotational = "Could not determine rotational"
return
if rotation == "1":
self.rotational = "Spinning disk"
else:
self.rotational = "SSD"
def populate_host(self, pcidata):
if self.sysfs_no_links == 1:
try:
sysdir = os.readlink(os.path.join(self.sysdir, "device"))
except:
pass
else:
sysdir = self.sysdir
m = re.match(".+/\d+:(\w+:\w+\.\w)/host\d+/\s*", sysdir)
if m:
pciid = m.group(1)
self.host = find_device(pcidata, pciid)
else:
self.host = ""
def populate_diskname(self):
m = re.match(".*/(.+)$", self.sysdir)
self.diskname = m.group(1)
def populate_holders(self):
for dir in os.listdir(self.sysdir + "/holders"):
if re.search("^dm-.*", dir):
try:
f = open(self.sysdir + "/holders/" + dir + "/dm/name")
name = f.read().rstrip()
f.close()
self.holders.append(name)
except IOError:
self.holders.append(dir)
else:
self.holders.append(dir)
def populate_discard(self):
try:
f = open(self.sysdir + "/queue/discard_granularity")
discard = f.read().rstrip()
f.close()
if discard == "0":
self.discard = "No"
else:
self.discard = "Yes"
except IOError:
self.discard = "No"
def populate_start(self):
try:
f = open(self.sysdir + "/start")
self.start = f.read().rstrip()
f.close()
except IOError:
pass
def populate_partitions(self):
for dir in os.listdir(self.sysdir):
m = re.search("(" + self.diskname + "\d+)", dir)
if m:
partname = m.group(1)
part = Device()
part.sysdir = self.sysdir + "/" + partname
part.populate_part_info()
self.partitions.append(part)
def populate_part_info(self):
""" Only call this if we are a partition """
self.populate_diskname()
self.populate_holders()
self.populate_sectors()
self.populate_start()
def populate_removable(self):
try:
f = open(self.sysdir + "/removable")
remove = f.read().rstrip()
f.close()
if remove == "1":
self.removable = "Yes"
else:
self.removable = "No"
except IOError:
self.removable = "No"
def populate_all(self, pcidata):
self.populate_diskname()
self.populate_holders()
self.populate_partitions()
self.populate_removable()
self.populate_model()
self.populate_vendor()
self.populate_sectors()
self.populate_sector_size()
self.populate_rotational()
self.populate_discard()
self.populate_host(pcidata)
p = Popen(["lspci"], stdout=PIPE)
err = p.wait()
if err:
print "Error running lspci"
sys.exit()
pcidata = p.stdout.read()
sysfs_no_links = 0
devices = []
if len(sys.argv) > 1:
m = re.match("/dev/(\D+)\d*", sys.argv[1])
if m:
block = m.group(1)
else:
block = sys.argv[1]
try:
path = os.readlink(os.path.join("/sys/block/", block))
except OSError, e:
if e.errno == errno.EINVAL:
path = block
else:
print "Invalid device name " + block
sys.exit()
d = Device()
d.sysdir = os.path.join("/sys/block", path)
d.populate_all(pcidata)
devices.append(d)
else:
for block in os.listdir("/sys/block"):
try:
if sysfs_no_links == 0:
path = os.readlink(os.path.join("/sys/block/", block))
else:
path = block
except OSError, e:
if e.errno == errno.EINVAL:
path = block
sysfs_no_links = 1
else:
continue
if re.search("virtual", path):
continue
if sysfs_no_links == 1:
sysdir = os.path.join("/sys/block", path)
if virtual_device(sysdir) == 1:
continue
d = Device()
d.sysdir = os.path.join("/sys/block", path)
d.sysfs_no_links = sysfs_no_links
d.populate_all(pcidata)
devices.append(d)
for d in devices:
print d.diskname
print "\tHost: " + d.host
print "\tVendor: " + d.vendor
print "\tModel: " + d.model
print "\tSector size (bytes): " + d.sectorsize
print "\tSectors: " + d.sectors
size = float(d.sectors) * float(d.sectorsize)
pretty = pretty_size(size)
print "\tSize: " + pretty
print "\tRemovable: " + d.removable
print "\tDisk type: " + d.rotational
print "\tSupports discard: " + d.discard
if len(d.holders) > 0:
print "\tHolders:"
for h in d.holders:
print "\t\t" + h
if len(d.partitions) > 0:
print "\tPartitions:"
for p in d.partitions:
print "\t\t" + p.diskname
print "\t\t\tStart sector: " + p.start
print "\t\t\tSectors: " + p.sectors
size = float(p.sectors) * float(d.sectorsize)
pretty = pretty_size(size)
print "\t\t\tSize: " + pretty
if len(p.holders) > 0:
print "\t\t\tHolders:"
for h in p.holders:
print "\t\t\t\t" + h
输出示例
输出磁盘信息比直观易理解
sda
Host:
Vendor: ATA
Model: CentOS Linux 7-0
Sector size (bytes): 512
Sectors: 134217728
Size: 64.00GiB
Removable: No
Disk type: SSD
Supports discard: Yes
Partitions:
sda1
Start sector: 2048
Sectors: 2097152
Size: 1024.00MiB
sda2
Start sector: 2099200
Sectors: 132118528
Size: 63.00GiB
Holders:
cl-root
cl-swap
cl-home
sr0
Host:
Vendor:
Model: Virtual DVD-ROM
Sector size (bytes): 512
Sectors: 2097151
Size: 1024.00MiB
Removable: Yes
Disk type: Spinning disk
Supports discard: No
Python3的一个脚本,需要安装单独的包psutil
import psutil
import platform
from datetime import datetime
def get_size(bytes, suffix="B"):
"""
Scale bytes to its proper format
e.g:
1253656 => '1.20MB'
1253656678 => '1.17GB'
"""
factor = 1024
for unit in ["", "K", "M", "G", "T", "P"]:
if bytes < factor:
return f"{bytes:.2f}{unit}{suffix}"
bytes /= factor
print("="*40, "System Information", "="*40)
uname = platform.uname()
print(f"System: {uname.system}")
print(f"Node Name: {uname.node}")
print(f"Release: {uname.release}")
print(f"Version: {uname.version}")
print(f"Machine: {uname.machine}")
print(f"Processor: {uname.processor}")
# Boot Time
print("="*40, "Boot Time", "="*40)
boot_time_timestamp = psutil.boot_time()
bt = datetime.fromtimestamp(boot_time_timestamp)
print(f"Boot Time: {bt.year}/{bt.month}/{bt.day} {bt.hour}:{bt.minute}:{bt.second}")
# let's print CPU information
print("="*40, "CPU Info", "="*40)
# number of cores
print("Physical cores:", psutil.cpu_count(logical=False))
print("Total cores:", psutil.cpu_count(logical=True))
# CPU frequencies
cpufreq = psutil.cpu_freq()
print(f"Max Frequency: {cpufreq.max:.2f}Mhz")
print(f"Min Frequency: {cpufreq.min:.2f}Mhz")
print(f"Current Frequency: {cpufreq.current:.2f}Mhz")
# CPU usage
print("CPU Usage Per Core:")
for i, percentage in enumerate(psutil.cpu_percent(percpu=True, interval=1)):
print(f"Core {i}: {percentage}%")
print(f"Total CPU Usage: {psutil.cpu_percent()}%")
# Memory Information
print("="*40, "Memory Information", "="*40)
# get the memory details
svmem = psutil.virtual_memory()
print(f"Total: {get_size(svmem.total)}")
print(f"Available: {get_size(svmem.available)}")
print(f"Used: {get_size(svmem.used)}")
print(f"Percentage: {svmem.percent}%")
print("="*20, "SWAP", "="*20)
# get the swap memory details (if exists)
swap = psutil.swap_memory()
print(f"Total: {get_size(swap.total)}")
print(f"Free: {get_size(swap.free)}")
print(f"Used: {get_size(swap.used)}")
print(f"Percentage: {swap.percent}%")
# Disk Information
print("="*40, "Disk Information", "="*40)
print("Partitions and Usage:")
# get all disk partitions
partitions = psutil.disk_partitions()
for partition in partitions:
print(f"=== Device: {partition.device} ===")
print(f" Mountpoint: {partition.mountpoint}")
print(f" File system type: {partition.fstype}")
try:
partition_usage = psutil.disk_usage(partition.mountpoint)
except PermissionError:
# this can be catched due to the disk that
# isn't ready
continue
print(f" Total Size: {get_size(partition_usage.total)}")
print(f" Used: {get_size(partition_usage.used)}")
print(f" Free: {get_size(partition_usage.free)}")
print(f" Percentage: {partition_usage.percent}%")
# get IO statistics since boot
disk_io = psutil.disk_io_counters()
print(f"Total read: {get_size(disk_io.read_bytes)}")
print(f"Total write: {get_size(disk_io.write_bytes)}")
# Network information
print("="*40, "Network Information", "="*40)
# get all network interfaces (virtual and physical)
if_addrs = psutil.net_if_addrs()
for interface_name, interface_addresses in if_addrs.items():
for address in interface_addresses:
print(f"=== Interface: {interface_name} ===")
if str(address.family) == 'AddressFamily.AF_INET':
print(f" IP Address: {address.address}")
print(f" Netmask: {address.netmask}")
print(f" Broadcast IP: {address.broadcast}")
elif str(address.family) == 'AddressFamily.AF_PACKET':
print(f" MAC Address: {address.address}")
print(f" Netmask: {address.netmask}")
print(f" Broadcast MAC: {address.broadcast}")
# get IO statistics since boot
net_io = psutil.net_io_counters()
print(f"Total Bytes Sent: {get_size(net_io.bytes_sent)}")
print(f"Total Bytes Received: {get_size(net_io.bytes_recv)}")
输出示例
======================================== System Information ========================================
System: Darwin
Node Name: dushibings-MacBook-Pro.local
Release: 19.5.0
Version: Darwin Kernel Version 19.5.0: Tue May 26 20:41:44 PDT 2020; root:xnu-6153.121.2~2/RELEASE_X86_64
Machine: x86_64
Processor: i386
======================================== Boot Time ========================================
Boot Time: 2020/7/13 13:24:16
======================================== CPU Info ========================================
Physical cores: 4
Total cores: 8
Max Frequency: 2900.00Mhz
Min Frequency: 2900.00Mhz
Current Frequency: 2900.00Mhz
CPU Usage Per Core:
Core 0: 49.5%
Core 1: 5.9%
Core 2: 34.3%
Core 3: 4.0%
Core 4: 35.6%
Core 5: 4.0%
Core 6: 31.0%
Core 7: 4.0%
Total CPU Usage: 20.9%
======================================== Memory Information ========================================
Total: 16.00GB
Available: 5.64GB
Used: 9.05GB
Percentage: 64.7%
==================== SWAP ====================
Total: 3.00GB
Free: 1.05GB
Used: 1.95GB
Percentage: 65.0%
======================================== Disk Information ========================================
Partitions and Usage:
=== Device: /dev/disk1s5 ===
Mountpoint: /
File system type: apfs
Total Size: 465.63GB
Used: 10.41GB
Free: 156.19GB
Percentage: 6.3%
=== Device: /dev/disk1s1 ===
Mountpoint: /System/Volumes/Data
File system type: apfs
Total Size: 465.63GB
Used: 294.30GB
Free: 156.19GB
Percentage: 65.3%
=== Device: /dev/disk1s4 ===
Mountpoint: /private/var/vm
File system type: apfs
Total Size: 465.63GB
Used: 4.00GB
Free: 156.19GB
Percentage: 2.5%
Total read: 141.10GB
Total write: 169.03GB
======================================== Network Information ========================================
=== Interface: lo0 ===
IP Address: 127.0.0.1
Netmask: 255.0.0.0
Broadcast IP: None
=== Interface: lo0 ===
=== Interface: lo0 ===
=== Interface: en0 ===
IP Address: 192.168.100.28
Netmask: 255.255.255.0
Broadcast IP: 192.168.100.255
=== Interface: en0 ===
=== Interface: en0 ===
=== Interface: vnic0 ===
IP Address: 10.211.55.2
Netmask: 255.255.255.0
Broadcast IP: 10.211.55.255
=== Interface: vnic0 ===
=== Interface: vnic1 ===
IP Address: 10.37.129.2
Netmask: 255.255.255.0
Broadcast IP: 10.37.129.255
=== Interface: vnic1 ===
=== Interface: en1 ===
=== Interface: en2 ===
=== Interface: en3 ==
=== Interface: en4 ===
Total Bytes Sent: 3.69GB
Total Bytes Received: 27.65GB
总结:
基于Python2.7的脚本实际使用意义最大,可以减少通过单独的命令去获取系统信息,并且基于ansible可以实现批量的系统信息查看,但是python3的脚本获取的信息最全面,大家可以结合自己的需求进行搭配使用。
源码下载: https://github.com/Dushibing/Linux_System_investigate