How to use Python to obtain Linux system information

Source: Internet
Author: User
Tags glob string methods
In this article, we will explore how to use Python to retrieve Linux system information. Go to you.

Which Python version?

When I mention Python, it refers to CPython 2 (accurate: 2.7 ). I will explicitly remind those same code that does not work on CPython 3 (3.3) and provide an alternative code that explains the differences. Make sure that you have installed CPython. enter python or python3 on the terminal and press enter. then, you can see the python prompt (prompt) on the terminal ).

Please note that all programs are # in their first line #! /Usr/bin/env/python, that is, we want the Python interpreter to execute these scripts. Therefore, if you want your script to be executable, use the chmod + x your-script.py, then you can use. /your-script.py to execute it (in this article you will see this way)

Explore the platform module

In the standard library, the platform module runs many functions that we obtain a large amount of system information. Let's run the Python interpreter to explore some of their functions. let's start with the platform. uname () function:

>>> 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')

If you already know the linux uname command, you will recognize that this function is an interface of this command. On Python 2, it returns a tuple containing the system type (or kernel version), host name, version, release version, hardware of the machine, and processor information ). You can use subscript to access individual attributes, as shown in the following code:

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

On Python 3, this function returns a name tuples:

>>> 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:29UTC 2013', machine='x86_64', processor='x86_64')

Because the returned results are named tuples, you can simply specify specific attributes by name instead of remembering the subscript, as shown in the following code:

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

The platform module also has some direct interfaces for the above attributes, such:

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

The linux_distribution () function returns detailed information about your linux release version. For example, on the Fedora 18 system, the command returns the following information:

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

The returned result contains the version release name, version, and code tuples. The value displayed by _ supported_dists can be obtained from the release versions supported by specific Python versions.

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

If your linux release version is not included (or is a derivative release of one of them ). Then you probably call the above function without any useful information.

The last function of the platform module. we will look at the architecture () function. When you call this function without any parameters, it returns the tuples that contain the number of architectural digits and the executable format of python, such:

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

On a 32-bit system, you will see:

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

If you specify any other executable on the system, you will get similar results, as shown in the following code:

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

We encourage you to explore other functions in the platform module and find the Python version you are running. If you want to know how this module obtains this information, you can go deep into the Lib/platform. py file in the PYthon source code directory.

The OS and sys modules can also obtain some system attributes, such as native bytecode. Next, we will go beyond the Python standard library module and explore some ways to make access information possible through proc and sysfs file systems in linux. Note that accessing information through the file system will be different in different hardware architectures. Therefore, when reading this article or writing a script, always remember to try to get information from these files.

CPU information

The/proc/cpuinfo file contains information about your system processor units. For example, here is what the python linux command cat/proc/cpuinfo does:

#! /usr/bin/env python""" print out the /proc/cpuinfo    file"""from __future__ import print_functionwith open('/proc/cpuinfo') as f:    for line in f:        print(line.rstrip('\n'))

When you use Python 2 or Python 3 to execute this program, you will see all/proc/cpuinfo content on the screen (in the above program, rstrip () to delete line breaks at the end of each line)

The following code lists how to use the startwith () string method to display the mode of your processor unit.

#! /usr/bin/env python""" Print the model of your     processing units"""from __future__ import print_functionwith 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)

When you run this program, you should see the pattern name of each of your processor units. For example, this is what I see on my computer.

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

So far, we have two ways to figure out the architecture of the system we are using. Technically, the two methods actually report the kernel architecture that your system runs. Therefore, if your computer is 64-bit, however, the 32-bit kernel is running, and the above method will still display as a 32-bit architecture. You can find the lm logo from the logo listed in/proc/cpuinfo to find the real architecture of your brain. The lm flag indicates the long mode. only the 64-bit architecture displays the long mode. The following program will guide you through:

#! /usr/bin/env python""" Find the real bit architecture"""from __future__ import print_functionwith 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')

As we can see, it is possible to read the/proc/cpuinfo file and use simple text processing technology to obtain the data we are looking. To better use the data for other programs, a better idea is to make the content of/proc/cpuinfo into a standard data structure, such as a dictionary ). Note: If you view the content of this file, you will find that there are many key-value pairs for each processor unit (in the previous example, we printed the model name of each processor, that is, the model name is the keyword ). Information of different processor units can be separated by blank lines. It is very easy to construct a dictionary data structure containing keywords for each processor unit. For each keyword, the value of the processor unit is in the/proc/cpuinfo file. The following code will guide you on how to do this.

#!/usr/bin/env/ python"""/proc/cpuinfo as a Python dict"""from __future__ import print_functionfrom collections import OrderedDictimport pprintdef 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 cpuinfoif __name__=='__main__':    cpuinfo = cpuinfo()    for processor in cpuinfo.keys():        print(cpuinfo[processor]['model name'])

This code uses OrderedDict (ordered Dictionary) instead of conventional dictionary, which can be stored in files in an ordered manner using key values. Therefore, the data of the first processor unit is the data of the second processor unit, and so on. You can use a filter to filter the information you are looking for (as shown in the if _ name _ = '_ main _' block ). The above program prints the model name of each processor unit after each execution (as indicated by the cpuinfo [processor] ['model name'] statement)

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

Similar to/proc/cpuinfo, the file/proc/meminfo contains information about your computer's primary storage. The following program creates a dictionary that fills in the content of this file.

#!/usr/bin/env pythonfrom __future__ import print_functionfrom collections import OrderedDictdef 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 meminfoif __name__=='__main__':    #print(meminfo())        meminfo = meminfo()    print('Total memory: {0}'.format(meminfo['MemTotal']))    print('Free memory: {0}'.format(meminfo['MemFree']))

Like the previous keyword, you can access any specified information you query (expressed in the if _ name __=__ main _ block ). When you execute this program, you will see the output like the following:

Total memory: 7897012 kBFree memory: 249508 kB
Network statistics

Next, we will explore the network devices of our computer system. We will obtain the network interface of the system and the information about sending and receiving data through the system after the system is restarted. The/proc/net/dev file makes the information available. If you check the content of this file, you will notice that the first line or two contains header information. The first column of this file is the network interface name, the second and third columns display the number of bytes received and sent (such as the total number of sent bytes, number of packets, and errors ). What we are interested in here is that they are sad that different network devices extract the total sent data and received data. The following code shows how to extract the information from the/proc/net/dev file.

#!/usr/bin/env pythonfrom __future__ import print_functionfrom collections import namedtupledef 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_dataif __name__=='__main__':        netdevs = netdevs()    for dev in netdevs.keys():        print('{0}: {1} MiB {2} MiB'.format(dev, netdevs[dev].rx, netdevs[dev].tx))

When you run the above program, the following output will show the total data received and sent by network devices after your recent restart, in MB.

em1: 0.0 MiB 0.0 MiBwlan0: 2651.40951061 MiB 183.173976898 MiB

You can use persistent data storage mechanisms to connect and write your own data using monitoring programs.

Process information

The/proc directory contains the directories of all running processes. These directories have the same name as the process identifier. Therefore, if you traverse the directories under the/proc directory that use numbers as their names, you will get a list of all processes that are currently running. In the following code, the process_list () function returns the list of identifiers of all processes currently running. After you execute this program, the list length is the total number of processes running on the system.

#!/usr/bin/env python""" List of all process IDs currently active"""from __future__ import print_functionimport osdef process_list():    pids = []    for subdir in os.listdir('/proc'):        if subdir.isdigit():            pids.append(subdir)    return pidsif __name__=='__main__':    pids = process_list()    print('Total number of running processes:: {0}'.format(len(pids)))

After the above program is executed, the output similar to the following is displayed:

Total number of running processes:: 229

Each process directory contains some other files and directories, such as the call of process commands, the shared libraries it is using, and other.

Block Device

The next program lists all block devices by reading the sysfs virtual file system. Block devices in your system can be found in the/sys/block directory. Therefore, directories such as/sys/block/sda and/sys/block/sdb may exist. To obtain all these devices, we use regular expressions to scan/sys/block directories and extract block devices that are of interest.

#!/usr/bin/env python"""Read block device data from sysfs"""from __future__ import print_functionimport globimport reimport os# Add any other device pattern to read fromdev_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()

If you run the program, you will see the following similar output:

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

When I run the program, there is an SD memory card inserted into the computer, so you will see it detected by the program. You can also expand the program to identify other block devices (such as virtual hard disks ).

Create a command line utility

In linux, the command line tool is ubiquitous [@ Lesus Note: Someone once said that if linux does not have a command line, it is a scum.], It allows people to specify command line parameters to customize the default behavior of the program. The argparse module provides an interface similar to the linux command line utility. The following code shows how a program obtains all users on the system and prints their logon shells (using the pwd standard library module ):

#!/usr/bin/env python"""Print all the users and their login shells"""from __future__ import print_functionimport pwd# Get the users from /etc/passwddef getusers():    users = pwd.getpwall()    for user in users:        print('{0}:{1}'.format(user.pw_name, user.pw_shell))if __name__=='__main__':    getusers()

After running this program, it prints all the users on the system and their logon shell names.

Now, the user you want to program can choose whether to view system users (such as daemon and apache ). We expanded the previous code and used the argparse module for the first time to implement this feature, as shown below.

#!/usr/bin/env python"""Utility to play around with users and passwords on a Linux system"""from __future__ import print_functionimport pwdimport argparseimport osdef 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/passwddef 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 <= uid_max:                print('{0}:{1}'.format(user.pw_name, user.pw_shell))        else:            print('{0}:{1}'.format(user.pw_name, user.pw_shell))if __name__=='__main__':    parser = argparse.ArgumentParser(description='User/Password Utility')    parser.add_argument('--no-system', action='store_true',dest='no_system',                        default = False, help='Specify to omit system users')    args = parser.parse_args()    getusers(args.no_system)

Run the preceding program using the -- help option, and you will see friendly help information: options and their functions.

$ ./getusers.py --helpusage: getusers.py [-h] [--no-system]User/Password Utilityoptional arguments:  -h, --help   show this help message and exit  --no-system  Specify to omit system users

The preceding example is as follows:

$ ./getusers.py --no-systemgene:/bin/bash

When you input an invalid parameter, the program will complain (an error is reported)

$ ./getusers.py --paramusage: getusers.py [-h] [--no-system]getusers.py: error: unrecognized arguments: --param

In the above program, we briefly understood how to use the argparse module. Parser = argparse. ArgumentParser (description = "User/Password Utility") statement creates an ArgumentParser object with an optional description indicating what the program is doing,

Then, we add parameters. We want the program to recognize the next statement add_argument (). Parser. add_argument ('-- no-system', action = 'store _ true', dest = 'no _ system', default = False, help = 'specify to omit system users '). The parameter of the first method is that when the system calls this program, the program uses the name of the parameter to be provided. the following parameter acton = store_true indicates that it is a boolean choice. That is to say, it really or falsely affects certain behaviors of the program. Dest is a customizable parameter, and its value can be provided to the program. If this value is not provided by the user, the default value is false. The help information displayed by the final parameter program. Finally, the parameter is parsed using the args = parser. parse_args () method. Once the Parsing method is implemented, the value of the user option can be crawled through the corresponding syntax parameter option_dest. when you configure the parameter, option_dest is a specific target variable. The getusers (args. no_system) statement uses the value of the parameter provided by the user to call back the getusers () method.

The following program shows how to specify a non-Boolean option. This program is a rewriting of 6th programs, and an option is attached to specify the network devices you are interested in.

#!/usr/bin/env pythonfrom __future__ import print_functionfrom collections import namedtupleimport argparsedef netdevs(iface=None):    ''' 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 not iface:            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))        else:            if line[0].strip() == iface:                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_dataif __name__=='__main__':    parser = argparse.ArgumentParser(description='Network Interface Usage Monitor')    parser.add_argument('-i','--interface', dest='iface',                        help='Network interface')    args = parser.parse_args()    netdevs = netdevs(iface = args.iface)    for dev in netdevs.keys():        print('{0}: {1} MiB {2} MiB'.format(dev, netdevs[dev].rx, netdevs[dev].tx))

When you execute a program without any parameters, the behavior of the program is exactly the same as that of the previous version. Then, you can specify the network device you are interested in. For example:

$ ./net_devs_2.pyem1: 0.0 MiB 0.0 MiBwlan0: 146.099492073 MiB 12.9737148285 MiBvirbr1: 0.0 MiB 0.0 MiBvirbr1-nic: 0.0 MiB 0.0 MiB$ ./net_devs_2.py  --helpusage: net_devs_2.py [-h] [-i IFACE]Network Interface Usage Monitoroptional arguments:  -h, --help            show this help message and exit  -i IFACE, --interface IFACE                        Network interface$ ./net_devs_2.py  -i wlan0wlan0: 146.100307465 MiB 12.9777050018 MiB
Availability of the script's system scope

With the help of this article, you may already be able to write one or more useful scripts. just like other linux commands, you want to use them every day. The simplest way is to set the script to executable, and then set a BASH alias for the script. You can also remove the. py extension and place the script in a standard location such as/usr/local/sbin.

Other useful standard library modules

In addition to the standard library modules mentioned in this article, there are many other useful standard modules: subprocess, ConfigParser, readline, and curses.

What to do next?

At this stage, you can use your own Python experience to explore the Linux system. you can refer to any of the following methods. If you have to write a lot of shell scripts/command lines to explore Linux, try Python. If you want to write a utility script that executes many tasks in a simpler way, try Python. Finally, if you have already used Python to avoid writing programs for other purposes on Linux, try to use Python to explore Linux.

Resource Python resource
  • Lists


  • Tuples


  • Namedtuples


  • OrderedDict


  • Split ()


  • Strip () rstrip () and other string methods


  • Reading and writing files


  • OS module


  • Platform module


  • Pwd module


  • Spwd module


  • Grp module


  • Subprocess module


  • ConfigParser module


  • Readline module

System Information
  • Long Mode


  • /Proc file system


  • Sysfs

Address: http://amitsaha.github.io/site/notes/articles/python_linux/article.html

The above describes how to use Python to obtain detailed information about Linux systems. For more information, see other related articles in the first PHP community!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.