Which Python version?
When I mentioned Python, I was referring to CPython 2 (exactly 2.7). I will explicitly remind those same code that it is not working on CPython 3 (3.3) and provide an alternative code that explains the differences. Make sure you have CPython installed, enter Python or Python3 carriage return on the terminal, and you should see the Python prompt (prompt) on the terminal.
Note that all the programs in their first line are #!/usr/bin/env/python, that is, we want the Python interpreter to execute these scripts. So if you want your script to be executable, use chmod +x your-script.py, then you can use./your-script.py to execute it (as you'll see in this article)
Explore the Platform Module
The platform module is in the standard library, and it has a lot of functions that run our access to many system information. Let's run the Python interpreter to explore some of these functions, starting with the Platform.uname () function:
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 version, 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 Jan 16:44:29utc ', machine= ' x86_64 ', processor= ' x86_64 ')
Because the returned result is a named tuple, you can simply specify a specific property by its 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 details about the release of Linux that you are on. For example, on a Fedora 18 system, this command returns the following information:
>>> platform.linux_distribution ()
(' Fedora ', ' spherical ', ' Cow ')
The return result contains the version release name, version, and the symbol tuple. The published version supported by the specific Python version can be obtained by _supported_dists the value displayed.
>>> platform._supported_dists (' SuSE ', ' Debian ', ' fedora ', ' redhat ', ' CentOS ', ' Mandrake ', ' Mandriva ', ' Rocks ' , ' Slackware ', ' yellowdog ', ' Gentoo ', ' unitedlinux ', ' turbolinux ')
If your Linux release is not in one of these (or one of the derivative distributions). Then you are likely to call the above function without seeing any useful information.
Platform the last function of the module, we will look at the architecture () function. When you call this function without a parameter, it returns a tuple that contains the number of schema bits and the format of the Python executable, like this:
>>> Platform.architecture ()
(' 64bit ', ' ELF ')
On a 32-bit system, you will see:
>>> Platform.architecture ()
(' 32bit ', ' ELF ')
If you specify anything else on the system that you can perform, you will get similar results, like this:
>>> platform.architecture (executable= '/usr/bin/ls ')
(' 64bit ', ' ELF ')
Encourage exploring the other functions of the Platform module, in addition to these, to find out which version of Python you are running now. If you want to know how this module is getting this information, you can drill down into the lib/platform.py file in the Python source directory.
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 the 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 or write a script, always remember 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 is 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_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 the/proc/cpuinfo content on the screen (in the above program, the Rstrip () method is used to delete the line break 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_functionwith open ('/PR Oc/cpuinfo ') as F: For line on F: # Ignore The blank line separating the information between # details about T WO 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 schema 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.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've had two ways to figure out the architecture of the system we're using. Technically correct, two ways of actually reporting the kernel architecture of your system, so if your computer is 64-bit, but it is running a 32-bit kernel, then the above method will be displayed as a 32-bit schema. You can find the true architecture of your computer by looking for the LM flag from the/proc/cpuinfo list of flags. The LM flag represents a long mode, and only 64-bit architectures will display it. The following program will guide you on how to do it:
#! /usr/bin/env python "" "Find the Real Bit Architecture" "" from __future__ import Print_functionwith open ('/proc/cpuinfo ') a s F: For line in F: # Ignore The blank line separating the information between # details about the 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 the/proc/cpuinfo file and use simple text processing techniques to get the data we are looking for. In order to better use this data for other programs, a better idea is to make/proc/cpuinfo content a standard data structure, such as a Dictionary (dictionary). This 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 have printed the model name of each processor, that is, the model name is the keyword). Information for different processor units can be separated by blank lines. It is very simple to construct a dictionary data structure containing the keywords for each processor unit. For each keyword, the value for the processor unit is in the/proc/cpuinfo file. The following code will guide you on how to do it.
#!/usr/bin/env/python "" "/proc/cpuinfo as a python dict" "from __future__ Import print_functionfrom collections Import Or Dereddictimport 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< c14/># 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 a ordereddict (ordered dictionary) instead of a regular dictionary, which can be stored in a file in an orderly manner using key values. Therefore, the data for the first processor unit is followed by the data of 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). Each execution of the above program prints the model name of each processor unit (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
Similar to/proc/cpuinfo, the file/proc/meminfo contains information about the main memory of your computer. The following program creates a dictionary populated with the contents 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, through its keywords, you can access any of the specified information you query (indicated in the If __name__==__main__ block). When you execute this program, you should see output similar to the following:
Total memory:7897012 KB
Free memory:249508 KB
Network statistics information
Next, we will explore the network equipment of our computer system. We will have access to the system's network interfaces and the information that sends and receives data through their data after the system restarts. The/proc/net/dev file makes this information available. If you check the contents of this file, you will notice that the head one or two line contains header information and so on, the first column of this file is the network interface name, the second and third columns show the number of bytes received and sent information (such as the total number of bytes sent, the number of packets, errors, etc.). What we're interested in here is that he's sad. Different network devices extract the total sent data and receive data. The following code shows how to extract this 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 () Dev ice_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 output below shows the total amount 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 and write your own data usage monitoring program.
Process information
The/proc directory contains all the running process directories. The names of these directories are the same as the process identifiers. So, if you traverse the directories in the/proc directory that use numbers as their names, you get a list of all the processes that are now running. In the following code, the Process_list () function returns a list of all the identifiers of the processes that are now running. When you execute this 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_functionimport osdef proc Ess_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)))
The above program displays output similar to the following when executed:
Total number of running processes:: 229
Each process directory contains a number of other files and directories, such as calls to process commands, shared libraries It is using, and others.
Each process directory contains a number of other files and directories, such as calls to process commands, shared libraries It is using, and others.
Block devices
The next program lists all the block devices by reading the SYSFS virtual file system. The block devices in your system can be found in the/sys/block directory. Therefore, there may be/SYS/BLOCK/SDA,/sys/block/sdb and so on such a directory. To get all of these devices, we use regular expressions to scan the/sys/block directory for the block device of interest.
#!/usr/bin/env python "" "Read block device data from Sysfs" "" from __future__ import print_functionimport globimport reimpo RT os# ADD Any other device pattern to read Fromdev_pattern = [' sd.* ', ' mmcblk* ']def size (device): nr_sectors = open (de Vice+ '/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): print (' device:: {0}, Size:: {1} GiB '. Format (device , size (device))) if __name__== ' __main__ ': Detect_devs ()
If you run the program, you will see a similar output as follows:
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 it detected by the program. You can also extend the program to identify other block devices (such as virtual hard disks).
Creating a command-line utility
Command-line tools are ubiquitous in Linux [@Lesus Note: It has been said that Linux does not have a command line is a slag. ], which allows a person to specify command-line arguments to customize the program's default behavior. The Argparse module provides an interface similar to the Linux command-line utility. The following code shows how the program obtains 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 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 will print all the users on the system and their login shell name.
Now, you want the user of the program to be able to choose whether to look at the system user (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 users and passwords on a Linux system" "from __future__ import Print_f Unctionimport pwdimport argparseimport osdef read_login_defs (): Uid_min = None Uid_max = None if Os.path.exists ('/etc/l Ogin.defs '): With open ('/etc/login.defs ') as F:login_data = F.readlines () for line in LOGIN_DATA:I F 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=f Alse): uid_min, Uid_max = Read_login_defs () if uid_min is None:uid_min = $ if Uid_max is None:uid_max = 6000 0 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)
Using the--HELP option to execute the above program, you will see friendly help information: options and their role.
$./getusers.py--help
usage:getusers.py [-h] [--no-system]
User/password Utility
Optional arguments:
-H,--help show this help message 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 will whine (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,
We then add the parameters. We want the program to be able 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 parameter, 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 final 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 the corresponding syntax parameter option_dest, when you configure the parameters, Option_dest is a target variable that you specify. 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 options for non-Boolean types. The program is a rewrite of the 6th program, with an option to specify which 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.re Adlines () 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 (li Ne[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 the program without any parameters, the program behaves exactly like the previous version. You can then specify the network devices that 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 Wlan0wlan 0: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 any other Linux command, and 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 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 you do next?
At this stage, depending on your own experience with Python, explore Linux inside, 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 inside, then try Python. If you want a simpler way to write utility scripts that perform many tasks, try Python. Finally, if you've already used Python to write other programs on Linux, try using Python to explore Linux inside.
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