Which Python version?
When I mentioned Python, I was referring to CPython 2 (exactly 2.7). I will explicitly remind those same code to not work on CPython 3 (3.3) and provide an alternate code that explains the difference. Make sure you have the CPython installed, enter Python or Python3 carriage return on the terminal, and you should be able to see the Python prompt (prompt) on the terminal.
Note that all of the programs are #!/usr/bin/env/python in their first line, that is, we want the Python interpreter to execute the scripts. So if you want your script to be executive, use chmod +x your-script.py, then you can use./your-script.py to execute it (you'll see this in this article)
Explore the Platform Module
The platform module is in the standard library, and it has a lot of functions that run the many system information we get. Let's run the Python interpreter to explore some of these functions, starting with the Platform.uname () function:
>>> Import Platform
>>> platform.uname ()
(' Linux ', ' fedora.echorand ', ' 3.7.4-204.fc18.x86 _64 ', ' #1 SMP Wed 16:44:29 UTC 2013 ', ' x86_64 ')
If you already know the uname command on Linux, you will recognize that this function is an interface to this command. On Python 2, it returns a system-type (or kernel version), host name, version, release, machine hardware, and processor information tuple (tuple). You can use the subscript to access individual properties, like this:
>>> platform.uname () [0]
' Linux '
On Python 3, this function returns a named tuple:
>>> platform.uname ()
uname_result (system= ' Linux ', node= ' Fedora.echorand ',
release= ' 3.7.4-204. Fc18.x86_64 ', version= ' #1 SMP Wed 16:44:29 UTC 2013 ', machine= ' x86_64 ', processor= ' x86_64 '
)
Because the return result is a named tuple, you can simply specify a specific property by name, rather than having to remember the subscript, like this:
>>> platform.uname (). System
' Linux '
The Platform module also has a direct interface to the above properties, like this:
>>> Platform.system ()
' Linux '
>>> Platform.release ()
' 3.7.4-204.fc18.x86_64 '
The Linux_distribution () function returns detailed information about the Linux release version you are in. For example, on a Fedora 18 system, this command returns the following message:
>>> platform.linux_distribution ()
(' Fedora ', ', ', ' spherical Cow ')
The return result contains the version name, the version, and the code tuple. A release version supported by a specific Python version can be obtained by the value displayed on the _supported_dists.
>>> platform._supported_dists
(' SuSE ', ' Debian ', ' fedora ', ' redhat ', ' CentOS ', ' Mandrake ',
' Mandriva ', ' Rocks ', ' slackware ', ' yellowdog ', ' Gentoo ',
' unitedlinux ', ' turbolinux '
If your Linux release version is not in it (or one of the derivative distributions). Then you are likely to call the above function without seeing any useful information.
The last function of the platform module, we'll look at the architecture () function. When you call this function without a reference, it returns a tuple containing the number of schema bits and Python executable format, like this:
>>> 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, like this:
>>> platform.architecture (executable= '/usr/bin/ls ')
(' 64bit ', ' ELF ')
Encourage exploring the other functions of the Platform module, and find out what Python version you are running. If you want to know how this module gets this information, you can drill down to the lib/platform.py file in the Python source directory.
The OS and SYS modules can also obtain some system properties, such as native byte order. Next, we go beyond the Python standard library module to explore some of the possibilities of accessing information on Linux systems through proc and SYSFS file systems. Note that access to information through the file system will vary from one hardware architecture to another. So when you read this article or write a script, keep in mind that you can try to get information from these files.
CPU Information
The/proc/cpuinfo file contains information about your system's processor unit. For example, here's what the Python version of Linux command Cat/proc/cpuinfo does:
#! /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 '))
When you execute this program using Python 2 or Python 3, you will see all the/proc/cpuinfo on the screen (in the above program, the Rstrip () method is used to delete line breaks at the end of each line)
The following code lists the patterns that use the Startwith () string method to display your processor unit.
#! /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 to be Tween
# 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 your schema name for each processor unit. For example, this is what I see on my computer.
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
So far, we have two ways to find out the architecture of the system we use. Technically correct, two ways actually report the kernel architecture of your system running, so if your computer is 64-bit, but it runs a 32-bit kernel, then the above method will appear as a 32-bit schema. You can find the real architecture of your computer by looking for the LM flag from the flags listed in/proc/cpuinfo. The LM flag represents long mode, and only 64-bit schema will show it. The following procedure will guide you through:
#! /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
# detail s 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 have seen, it is possible to read/proc/cpuinfo files and use simple text processing techniques to get the data we are looking for. In order to better use the data for other programs, a better idea is to make/proc/cpuinfo content a standard data structure, such as a Dictionary (dictionary). The note is simple: If you look at the contents of this file, you will find that there are a number of key pairs for each processor unit (in the previous example, we printed the model name for each processor, i.e. the model name is the keyword). Information for different processor units can be separated by a blank line. It is easy to construct a dictionary data structure that contains keywords for each processor unit. For each keyword, the value for the processor unit is in the/proc/cpuinfo file. The following code will instruct you on what to do.
#!/usr/bin/env/python" "/proc/cpuinfo as a python dict" "from __future__ import Prin
T_function from Collections import ordereddict import Pprint def cpuinfo (): "Return" 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=NPR Ocs+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 () to processor in Cpuinfo.keys (): Print (cpui nfo[processor][' model name ')
This code uses a ordereddict (ordered dictionary) rather than a regular dictionary, which can be stored sequentially in a file using key values. So, the data for the first processor unit is then the data for the second processor unit, and so on. You can use filters to filter the information you are looking for (as demonstrated 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.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
Memory information
like/proc/cpuinfo, file/proc/meminfo contains information about the main memory of your computer. The following program creates a dictionary that uses the contents of this file to populate.
#!/usr/bin/env python from
__future__ import print_function from
collections import Ordereddict
def Meminfo (): ' Return to 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 '])
Like previous, through its keywords, you can access any specified information of your query (represented in the If __name__==__main__ block). When you perform this program, you should see output similar to the following:
Total memory:7897012 KB
Free memory:249508 KB
Network Statistics
Next, we'll explore the network devices for our computer system. We will have access to the network interfaces of the system and information about sending and receiving data through their data when the system restarts. /proc/net/dev files make this information available. If you check the contents of this file, you will notice that the header one or two line contains headers and so on, the first column of this file is the network interface name, and the second and third columns show the number of bytes received and sent (such as total bytes sent, packets, errors, and so on). What we're interested in here is that he's sad. Different network devices extract the total send data and receive the data. The following code shows how to extract this information from a/proc/net/dev file.
#!/usr/bin/env python
__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.read Lines ()
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))
When you run the above program, the following output shows the total number of data received and sent from the network device after your most recent reboot, in megabytes.
em1:0.0 MIB 0.0 MIB
wlan0:2651.40951061 MIB 183.173976898 MIB
You can use a persistent data storage mechanism to connect to write your own data using the monitoring program.
Process information
the/proc directory contains all the running process directories. The names of these directories are the same as the identifiers of the processes. So, if you traverse the directory in the/proc directory that uses numbers as their names, you will get a list of all the processes that are currently running. In the following code, the Process_list () function returns the list of identifiers for all currently running processes. When you execute the program, the length of the list 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_ 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)))
The above program, when executed, displays output similar to the following:
Total number of running processes:: 229
Each process directory contains a number of other files and directories, such as the invocation of a process command, the shared library it is using, and others.
Each process directory contains a number of other files and directories, such as the invocation of a process command, the shared library it is using, and others.
Block device
The next program lists all block devices by reading the SYSFS virtual file system. The block devices in your system can be found in the/sys/block directory. So there may be directories such as/SYS/BLOCK/SDA,/sys/block/sdb, and so on. To get all of these devices, we use regular expressions to scan the/sys/block directory for interesting block devices.
#!/usr/bin/env python "" "Read blocks device data from Sysfs" "' from
__future__ Import print_function< C5/>import glob
Import re
import os
# ADD any other device pattern to read
from dev_pattern = [' sd.* ', ' MMC Blk* ']
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 Sen D 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 GiB
Device::/sys/block/mmcblk0, Size:: 3.70703125 GiB
When I run the program, there is an SD memory card plugged into the computer, so you will see that the program detects it. You can also extend the program to identify other block devices (such as virtual hard disks).
To build a command line utility
The command line usage tool in Linux is ubiquitous [@Lesus Note: It has been said that Linux is a slag without a command line. , it allows people to specify command-line arguments 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 the program gets all the users on the system and the login shell that prints them (using the PWD standard library module):
#!/usr/bin/env python "" "Print all of the
users and their login shells" "" from
__future__ import Print_fun ction
import pwd
# Get the users from/etc/passwd
def getusers ():
users = Pwd.getpwall () to
user in U Sers:
print (' {0}:{1} '. Format (User.pw_name, User.pw_shell))
if __name__== ' __main__ ':
getusers ()
When this program is run, it prints all the users on the system and their login shell name.
Now, you want the program's users to be able to choose whether to look at System users (like Daemon, Apache). We extend the previous code and use the Argparse module for the first time to implement this feature, as follows.
#!/usr/bin/env python "" "" "Utility to play around with the 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.PA Th.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.st Artswith (' Uid_max '): Uid_max = Int (Line.split () [1].strip ()) return to 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 () to user in Users:if no_system:if
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 (ARG
S.no_system)
Use the--HELP option to perform the above procedure, and you will see friendly help information: optional and their role.
$./getusers.py--help
usage:getusers.py [-h] [--no-system]
User/password Utility
Optional arguments:
-H,--help show this Help and exit
--no-system specify to omit system users
An example used by the above program is as follows:
$./getusers.py--no-system
Gene:/bin/bash
When you pass in an illegal argument, the program complains (the error)
$./getusers.py--param
usage:getusers.py [-h] [--no-system]
getusers.py:error:unrecognized arguments:--param
In the above program, we have a simple understanding of how to use the Argparse module. Parser = Argparse. The Argumentparser (description= "User/password Utility") statement creates a Argumentparser object with an optional description of what the program does,
Then we add the 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 when the system calls the program, the program uses the name that will provide the parameter, and the next argument acton=store_true indicates that it is a Boolean selection. That is to say, it really or falsely affects certain behavior of the program. Dest is a customizable parameter, and its value can be provided to the program for use. If this value is not provided by the user, this value defaults to False. The last parameter program displays the Help information. Finally, the parameters are parsed through the Args=parser.parse_args () method. Once the parsing method is done, the value of the user option can be crawled to option_dest the corresponding syntax parameter, and when you configure the parameter, the option_dest is a specified destination variable. Getusers (Args.no_system) This statement uses the value of the user-supplied parameter to callback the Getusers () method.
The following program shows how to specify an option for a non-boolean type. The program is an override of the 6th program and has an option to specify which network device you are interested in.
#!/usr/bin/env python __future__ import print_function from collections import namedtuple import Argparse def netde VS (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.S Plit (': ') if not iface:if Line[0].strip ()!= ' lo ': Device_data[line[0].strip ()] = data (float (line[1].sp Lit () [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_data if __name__== ' __main__ ': parser = Argpar Se.
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 program behaves exactly the same as the previous version. You can then specify the network device that you are interested in. For example:
$./net_devs_2.py
em1:0.0 MIB 0.0 MIB
wlan0:146.099492073 MIB
12.9737148285 MIB virbr1:0.0 MIB 0.0 MIB virbr1-nic:0.0 MIB 0.0 MIB
$/net_devs_2.py--help
usage:net_devs_2.py [-h] [-I iface]
network Interface Us Age Monitor
Optional arguments:-H,--help show this help message and exit-I
iface,--interface iface< C12/>network interface
$./net_devs_2.py-i wlan0
wlan0:146.100307465 MIB 12.9777050018 MIB
system-wide availability of scripts
with the help of this article, you may already be able to write one or more useful scripts, just like other Linux commands, and you want to use them every day. The easiest way to do this is to set the script to executable, and then set a bash alias for the script. You can also remove the. py extension and then place the script in a standard location such as/usr/local/sbin.
Other useful standard library modules
In addition to the standard library modules already mentioned in this article, there are many other useful standard modules: subprocess, Configparser, ReadLine and curses.
What do we do next?
At this stage, depending on your own experience with Python, explore the inner Linux, you can refer to any of the following ways. If you ever need to write a lot of shell scripts/command lines to explore Linux internals, try Python. If you want a simpler way to write a utility script that performs many tasks, try Python. Finally, if you've already used Python to write other programs on Linux, try using Python to explore the inner Linux.
Resources
Python Resources
- 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
Original address: http://amitsaha.github.io/site/notes/articles/python_linux/article.html