当前位置:  编程技术>python

使用 Python 获取 Linux 系统信息的代码

    来源: 互联网  发布时间:2014-10-09

    本文导语:  哪个Python版本? 当我提及Python,所指的就是CPython 2(准确的是2.7).我会显式提醒那些相同的代码在CPython 3 (3.3)上是不工作的,以及提供一份解释不同之处的备选代码。请确保你已经安装了CPython,在终端上输入python或者python3回车,...

哪个Python版本?

当我提及Python,所指的就是CPython 2(准确的是2.7).我会显式提醒那些相同的代码在CPython 3 (3.3)上是不工作的,以及提供一份解释不同之处的备选代码。请确保你已经安装了CPython,在终端上输入python或者python3回车,然后你在终端上应该能看到python的提示符(prompt)。

请注意,所有的程序在它们第一行都是#!/usr/bin/env/python,也就是说,我们想要Python的解释器来执行这些脚本。因此,如果你想你的脚本具有执行性,请使用chmod +x your-script.py, 那么你就可以使用./your-script.py来执行它了(在本文中你将会看到这种方式)

探索platform模块
platform模块在标准库中,它有很多运行我们获得众多系统信息的函数。让我们运行Python解释器来探索它们中的一些函数,那就从platform.uname()函数开始吧:

>>> import platform 
>>> platform.uname() 
('Linux', 'fedora.echorand', '3.7.4-204.fc18.x86_64', '#1 SMP Wed Jan 23 16:44:29 UTC 2013', 'x86_64') 


如果你已知道linux上的uname命令,那么你就会认出来这个函数就是这个命令的一个接口。在Python 2上,它会返回一个包含系统类型(或者内核版本),主机名,版本,发布版本,机器的硬件以及处理器信息元组(tuple)。你可以使用下标访问个别属性,像这样:

>>> platform.uname()[0]
'Linux'

在Python 3上,这个函数返回的是一个命名元组:

>>> platform.uname()

uname_result(system='Linux', node='fedora.echorand',
release='3.7.4-204.fc18.x86_64', version='#1 SMP Wed Jan 23 16:44:29
UTC 2013', machine='x86_64', processor='x86_64')

因为返回结果是一个命名元组,这就可以简单地通过名字来指定特定的属性,而不是必须记住下标,像这样:

>>> platform.uname().system
'Linux'

platform模块还有一些上面属性的直接接口,像这样:

>>> platform.system()
'Linux'

>>> platform.release()
'3.7.4-204.fc18.x86_64'

linux_distribution()函数返回的有关你所在的linux发布版本的详细信息。例如,在Fedora 18系统上,这个命令会返回如下信息:

>>> platform.linux_distribution()
('Fedora', '18', 'Spherical Cow')

这个返回结果中包含了版本发布名,版本以及代号元组。特定的Python版本支持的发布版本上可以通过_supported_dists显示的值获得。

>>> platform._supported_dists
('SuSE', 'debian', 'fedora', 'redhat', 'centos', 'mandrake',
'mandriva', 'rocks', 'slackware', 'yellowdog', 'gentoo',
'UnitedLinux', 'turbolinux')

如果你的linux发布版本不在其中(或者其中之一的衍生发行版)。那么你很可能调用了上面这个函数而看不到任何有用的信息。

platform模块的最后一个函数,我们将会看看architecture()函数。当你无参的调用这个函数,它会返回包含架构位数以及python可执行的格式的元组,像这样:

>>> platform.architecture()
('64bit', 'ELF')

在32位的系统上,你将会看到:

>>> platform.architecture()
('32bit', 'ELF')

如果你指定了系统上其他任何可执行的,你都将会获得相似的结果,如同这样:

>>> platform.architecture(executable='/usr/bin/ls')
('64bit', 'ELF')

鼓励探索platform模块的除了这些的其它函数,找出你现在运行的Python版本。如果你想知道这个模块是如何获取这些信息的,你可以深入查看PYthon源码目录下的Lib/platform.py文件。

os和sys模块也可以获得一些系统属性,例如原生的字节序。接下来,我们超越Python标准库模块,去探索一些在linux系统通过proc和sysfs文件系统使之访问信息成为可能。注意的是通过文件系统来访问信息将会在不同的硬件架构有所不同。所以在读本文或是写脚本时要时刻记住可以试图从这些文件获取信息。

CPU信息
/proc/cpuinfo文件包含了你的系统处理器单元的信息。例如,这里就是python版的linux命令cat /proc/cpuinfo所做的事:

#! /usr/bin/env python
""" print out the /proc/cpuinfo
  file
"""

from __future__ import print_function

with open('/proc/cpuinfo') as f:
  for line in f:
    print(line.rstrip('n'))

当你使用Python 2 或者 Python 3执行这个程序时,你会在屏幕上看到所有/proc/cpuinfo的内容(在上面的程序里,rstrip()方法用来删除每行末尾的换行符)

在下面的代码里列举了使用startwith()字符串方法来显示你的处理器单元的模式。

#! /usr/bin/env python

""" Print the model of your 
  processing units

"""

from __future__ import print_function

with open('/proc/cpuinfo') as f:
  for line in f:
    # Ignore the blank line separating the information between
    # details about two processing units
    if line.strip():
      if line.rstrip('n').startswith('model name'):
        model_name = line.rstrip('n').split(':')[1]
        print(model_name)

当你运行这个程序后,你应该会看到你的每个处理器单元的模式名。例如,这里就是在我电脑上所看到的。

Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz
Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz
Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz
Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz

迄今为止,我们已有两种方式来找出我们所使用的系统的架构。从技术上讲是正确的,两个方 式实际上报告了你系统运行的内核架构,所以,如果你的电脑是64位的,但是运行的是32位的内核,然后上面的方法还是将会显示为32位的架构。你可以通过从/proc/cpuinfo所列举的标志中查找lm标志,来找到你的电 脑的真实的架构。lm标志代表了长模式,只有64位架构的才会显示它。下面的程序将会指导你怎样做:

#! /usr/bin/env python

""" Find the real bit architecture
"""

from __future__ import print_function

with open('/proc/cpuinfo') as f:
  for line in f:
    # Ignore the blank line separating the information between
    # details about two processing units
    if line.strip():
      if line.rstrip('n').startswith('flags') 
          or line.rstrip('n').startswith('Features'):
        if 'lm' in line.rstrip('n').split():
          print('64-bit')
        else:
          print('32-bit')


如我们所看到那样,读取/proc/cpuinfo文件以及使用简单文本处理技术就可以获得我们要查找的数据是可能的。为了给其他程序更好的使用这些数据,一个更好的主意就是使/proc/cpuinfo的内容成为标准的数据结构,譬如字典(dictionary)。这个注意很简单:如果你查看这个文件的内容,你就会发现对于每个处理器单元,都有好些键值对(在先前的例子中,我们打印了每个处理器的模型名,即模型名就是关键字)。不同的处理器 单元的信息可以使用空白行隔开。构造一个字典数据结构包含每个处理器单元的关键字是很简单的。对于每个关键字,对于处理器单元的值都在/proc/cpuinfo文件中。下面的代码将会指导你怎么做。

#!/usr/bin/env/ python

"""
/proc/cpuinfo as a Python dict
"""
from __future__ import print_function
from collections import OrderedDict
import pprint

def cpuinfo():
  ''' Return the information in /proc/cpuinfo
  as a dictionary in the following format:
  cpu_info['proc0']={...}
  cpu_info['proc1']={...}

  '''

  cpuinfo=OrderedDict()
  procinfo=OrderedDict()

  nprocs = 0
  with open('/proc/cpuinfo') as f:
    for line in f:
      if not line.strip():
        # end of one processor
        cpuinfo['proc%s' % nprocs] = procinfo
        nprocs=nprocs+1
        # Reset
        procinfo=OrderedDict()
      else:
        if len(line.split(':')) == 2:
          procinfo[line.split(':')[0].strip()] = line.split(':')[1].strip()
        else:
          procinfo[line.split(':')[0].strip()] = ''
      
  return cpuinfo

if __name__=='__main__':
  cpuinfo = cpuinfo()
  for processor in cpuinfo.keys():
    print(cpuinfo[processor]['model name'])

这段代码中使用了OrderedDict(有序字典)而不是常规的字典,能够使用键值有序的存储在文件里。所以,第一个处理器单元的数据之后就是第二个处理器单元的数据,以此类推。你可以使用过滤器来过滤你所查找的信息(如同在if __name__ == '__main__'块中演示的那样)。上面的程序每次执行后都会打印每个处理器单元的模型名(如通过cpuinfo[processor]['model name']语句表明的那样)


Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz
Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz
Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz
Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz

内存信息
和/proc/cpuinfo相似,文件/proc/meminfo包含了你电脑的主存的信息。下面的这个程序创建了一个使用这个文件的内容填充的字典。

#!/usr/bin/env python

from __future__ import print_function
from collections import OrderedDict

def meminfo():
  ''' Return the information in /proc/meminfo
  as a dictionary '''
  meminfo=OrderedDict()

  with open('/proc/meminfo') as f:
    for line in f:
      meminfo[line.split(':')[0]] = line.split(':')[1].strip()
  return meminfo

if __name__=='__main__':
  #print(meminfo())
  
  meminfo = meminfo()
  print('Total memory: {0}'.format(meminfo['MemTotal']))
  print('Free memory: {0}'.format(meminfo['MemFree']))

像先前的,通过它的关键字,你可以访问任何你查询的指定信息(在if __name__==__main__块中有所表示)。当你执行这个程序,你该会看到像下面类似的输出:

Total memory: 7897012 kB
Free memory: 249508 kB

网络统计信息
接下来,我们会探索我们电脑系统的网络设备。我们将会获得系统的网络接口,以及当系统重启之后通过它们数据发送和接受数据的信息。 /proc/net/dev文件让这些信息可用。如果你检查了这个文件的内容,你就会注意到头一两行包含了头信息等等,这个文件第一列是网络接口名,第二和第三列显示了接收和发送的字节数信息(例如总发送字节数,包数,错误等等)。这里我们所感兴趣的就是他哦难过不同的网络设备提取出总发送数据和接收数据。下面的代码展示了怎么从/proc/net/dev文件中提取出这些信息。

#!/usr/bin/env python
from __future__ import print_function
from collections import namedtuple

def netdevs():
  ''' RX and TX bytes for each of the network devices '''

  with open('/proc/net/dev') as f:
    net_dump = f.readlines()
  
  device_data={}
  data = namedtuple('data',['rx','tx'])
  for line in net_dump[2:]:
    line = line.split(':')
    if line[0].strip() != 'lo':
      device_data[line[0].strip()] = data(float(line[1].split()[0])/(1024.0*1024.0), 
                        float(line[1].split()[8])/(1024.0*1024.0))
  
  return device_data

if __name__=='__main__':
  
  netdevs = netdevs()
  for dev in netdevs.keys():
    print('{0}: {1} MiB {2} MiB'.format(dev, netdevs[dev].rx, netdevs[dev].tx))

当你运行上面的程序,下面这个输出就会显示从你最近重启之后网络设备总接收和发送的数据,单位为兆。

em1: 0.0 MiB 0.0 MiB
wlan0: 2651.40951061 MiB 183.173976898 MiB

你可以使用持久的数据存储机制来连接,来写出自己的数据使用监控程序。

进程信息
/proc目录包含了所有正运行的进程目录。这些目录的名字和进程的标识符是一样的。所以,如果你遍历/proc目录下那些使用数字作为它们的名字的目录,你就会获得所有现在正在运行的进程列表。在下面的代码中process_list()函数返回所有现在正在运行的进程的标识符列表。当你执行这个程序后,这个列表的长度就是在系统上运行的总进程数。

#!/usr/bin/env python
"""
 List of all process IDs currently active
"""

from __future__ import print_function
import os
def process_list():

  pids = []
  for subdir in os.listdir('/proc'):
    if subdir.isdigit():
      pids.append(subdir)

  return pids


if __name__=='__main__':

  pids = process_list()
  print('Total number of running processes:: {0}'.format(len(pids)))

上面的程序当执行后会显示和下面类似的输出:

Total number of running processes:: 229

每个进程目录包含了一些其他文件和目录,如进程命令的调用,它正使用的共享库以及其它的。

每个进程目录包含了一些其他文件和目录,如进程命令的调用,它正使用的共享库以及其它的。

块设备

下一个程序通过读sysfs虚拟文件系统列出所有块设备。你系统中的块设备可以从/sys/block目录中找到。因此可能会有/sys/block/sda、/sys/block/sdb等这样的目录。为了获取所有这些设备,我们使用正则表达式对/sys/block目录进行扫描提取感兴趣的块设备。

#!/usr/bin/env python

"""
Read block device data from sysfs
"""

from __future__ import print_function
import glob
import re
import os

# Add any other device pattern to read from
dev_pattern = ['sd.*','mmcblk*']

def size(device):
  nr_sectors = open(device+'/size').read().rstrip('n')
  sect_size = open(device+'/queue/hw_sector_size').read().rstrip('n')

  # The sect_size is in bytes, so we convert it to GiB and then send it back
  return (float(nr_sectors)*float(sect_size))/(1024.0*1024.0*1024.0)

def detect_devs():
  for device in glob.glob('/sys/block/*'):
    for pattern in dev_pattern:
      if re.compile(pattern).match(os.path.basename(device)):
        print('Device:: {0}, Size:: {1} GiB'.format(device, size(device)))

if __name__=='__main__':
  detect_devs()

如果你运行该程序,你将会看到下述类似的输出:


Device:: /sys/block/sda, Size:: 465.761741638 GiB 
Device:: /sys/block/mmcblk0, Size:: 3.70703125 GiB

当我运行该程序的时候,有个SD内存卡插在电脑上,因此你会看到程序检测到了它。你也可以扩展该程序识别其它块设备(比如虚拟硬盘)。

建立命令行实用工具
linux中命令行使用工具是无所不在的[@Lesus 注:曾有人说过:linux没有了命令行就是个渣。],它允许人么指定命令行参数来定制程序的默认行为。argparse模块就提供了和linux命令行实用工具类似的接口。下面的代码展示了程序如何获得系统上的所有用户以及打印它们的登录shell(使用了pwd标准库模块):

#!/usr/bin/env python

"""
Print all the users and their login shells
"""

from __future__ import print_function
import pwd


# Get the users from /etc/passwd
def getusers():
  users = pwd.getpwall()
  for user in users:
    print('{0}:{1}'.format(user.pw_name, user.pw_shell))

if __name__=='__main__':
  getusers()

当运行这个程序之后,它会打印系统上所有的用户以及他们登录shell名。
现在,你想要程序的用户能够选择是否想看系统用户(像daemon, apache)。我们扩展前面的代码,第一次使用argparse模块来实现这个特性,如下。

#!/usr/bin/env python

"""
Utility to play around with users and passwords on a Linux system
"""

from __future__ import print_function
import pwd
import argparse
import os

def read_login_defs():

  uid_min = None
  uid_max = None

  if os.path.exists('/etc/login.defs'):
    with open('/etc/login.defs') as f:
      login_data = f.readlines()
      
    for line in login_data:
      if line.startswith('UID_MIN'):
        uid_min = int(line.split()[1].strip())
      
      if line.startswith('UID_MAX'):
        uid_max = int(line.split()[1].strip())

  return uid_min, uid_max

# Get the users from /etc/passwd
def getusers(no_system=False):

  uid_min, uid_max = read_login_defs()

  if uid_min is None:
    uid_min = 1000
  if uid_max is None:
    uid_max = 60000

  users = pwd.getpwall()
  for user in users:
    if no_system:
      if user.pw_uid >= uid_min and user.pw_uid 

    
 
 

您可能感兴趣的文章:

  • linux不用命令方式读文件获取网络流量,如何使用C函数调用获取网络流量信息?
  • 急,,,怎样获取远程系统的CPU和内存使用率
  • curl不使用文件存取cookie php使用curl获取cookie示例
  • 怎么写个CGI程序获取远程linux主机的信息,如cpu使用率,内存使用等?
  • 如何获取客户端浏览器所使用的语言,特别是要区分简繁体!
  • 使用ps命令,如何使用系统命令根据进程名称获取进程和子进程的ID?除了ps,还有其它系统命令的办法吗?谢谢。
  • 使用Jquery获取带特殊符号的ID 标签的方法
  • sql server 使用ntile获取数据的例子
  • c语言在unix系统下,如何获取cpu使用率
  • hp_ux下如何使用java获取top信息
  • 怎样使用FTP递归获取文件夹下的所有文件及子文件夹?
  • [求助]如何获取一个程序所使用的系统调用和参数?
  • jquery使用$(element).is()来判断获取的tagName
  • ASP.NET使用Subtract方法获取两个日期之间的天数
  • 哪位编程高手知道如何编程实现获取进程的内存使用量信息(linux)
  • 多网卡多IP情况下如何通过脚本获取当前登录终端使用的ip?
  • 使用标准SAX解析XML文档如何获取文档编码信息及约束它的dtd文件路径.
  • linux中,获取系统的CPU、内存、硬盘使用情况该用什么函数?
  • 如何使用c语言获取当前系统的时间,就是那个秒数?
  • 请问,怎样通过程序方式,获取AIX系统当前的CPU, 内存使用情况?
  • 使用libpcap读取tcpdump抓取的文件并解析c代码实例
  • 哪位会使用代码保护工具WingGuard来保护java代码?
  • Django项目使用示例步骤及代码
  • 使用 C# 动态编译代码和执行的代码
  • TinyXML(c++下操作xml的库)介绍,下载地址及使用代码举例
  • 如何锁定源代码,一次只能有一个线程使用?
  • 使用libpcap实现抓包程序的步骤及代码示例
  • 如何使gcc后的代码,使用相对路径存在调试信息?
  • jquery代码-如何正确使用ToggleClass
  • jquery代码-如何使用多个属性来进行过滤
  • VIM的使用,代码缩进的问题
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • Python不使用print而直接输出二进制字符串
  • 使用setup.py安装python包和卸载python包的方法
  • Python namedtuple(命名元组)使用实例
  • python基础教程之python消息摘要算法使用示例
  • 如何使用linux下gdb来调试python程序
  • 使用python删除nginx缓存文件示例(python文件操作)
  • 在Python3中使用urllib实现http的get和post提交数据操作
  • pycharm 使用心得(九)解决No Python interpreter selected的问题
  • 在Python中使用SWIG调用C和C++程序
  • 使用python Django做网页
  • juqery的python实现:pyquery学习使用教程
  • Python开发的单词频率统计工具wordsworth使用方法
  • numpy官方下载安装以及numpy详细使用教程(Python科学计算)
  • python文件读写并使用mysql批量插入示例分享(python操作mysql)
  • Python数组条件过滤filter函数使用示例
  • python使用循环实现批量创建文件夹示例
  • Python pass 语句使用示例
  • 在python中的socket模块使用代理实例
  • python回调函数的使用方法
  • linux系统使用python监控apache服务器进程脚本分享
  • 新手使用ubuntu安装python和jdk不能,急求解~!!
  • C++ I/O 成员 tellg():使用输入流读取流指针
  • 在测试memset函数的执行效率时,分为使用Cash和不使用Cash辆种方式,该如何控制是否使用缓存?
  • C++ I/O 成员 tellp():使用输出流读取流指针
  • 求ibm6000的中文使用手册 !从来没用过服务器,现在急需使用它,不知如何使用! 急!!!!!
  • Office 2010 Module模式下使用VBA Addressof
  • 请问:在使用oracle数据库作开发时,是使用pro*c作开发好些,还是使用库函数如oci等好一些啊?或者它们有什么区别或者优缺点啊?
  • windows下tinyxml.dll下载安装使用(c++解析XML库)
  • 急求结果!!假设一个有两个元素的信号量集S,表示了一个磁带驱动器系统,其中进程1使用磁带机A,进程2同时使用磁带机A和B,进程3使用磁带机B。
  • tcmalloc内存泄露优化c++开源库下载,安装及使用介绍
  • c#中SAPI使用总结——SpVoice的使用方法




  • 特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    如何使gcc后的代码,使用相对路径存在调试信息? iis7站长之家