Learn Python Control Flow and Loops to Write and Tune Shell Scripts – Part 2
It is considered good practice to start a script with a statement that indicates the purpose of the script, the license terms under which it is released, and a revision history listing the changes that have been made. Although this is more of a personal preference, it adds a professional touch to our work.
Here’s the script that produces the output we shown at the top of this article. It is heavily commented so that you can understand what’s happening.
Take a few minutes to go through it before proceeding. Note how we use an if / else structure to determine whether the length of each field caption is greater than the value of the field itself.
Based on the result, we use empty characters to fill in the space between a field caption and the next. Also, we use the right number of dashes as separator between the field caption and its value below.
#!/usr/bin/python3 # Change the above line to #!/usr/bin/python if you don't have Python 3 installed # Script name: uname.py # Purpose: Illustrate Python's OOP capabilities to write shell scripts more easily # License: GPL v3 (http://www.gnu.org/licenses/gpl.html) # Copyright (C) 2016 Gabriel Alejandro Cánepa # Facebook / Skype / G+ / Twitter / Github: gacanepa # Email: gacanepa (at) gmail (dot) com # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # REVISION HISTORY # DATE VERSION AUTHOR CHANGE DESCRIPTION # ---------- ------- -------------- # 2016-05-28 1.0 Gabriel Cánepa Initial version # Import the os module import os # Assign the output of os.uname() to the the systemInfo variable # os.uname() returns a 5-string tuple (sysname, nodename, release, version, machine) # Documentation: https://docs.python.org/3.2/library/os.html#module-os systemInfo = os.uname() # This is a fixed array with the desired captions in the script output headers = ["Operating system","Hostname","Release","Version","Machine"] # Initial value of the index variable. It is used to define the # index of both systemInfo and headers in each step of the iteration. index = 0 # Initial value of the caption variable. caption = "" # Initial value of the values variable values = "" # Initial value of the separators variable separators = "" # Start of the loop for item in systemInfo: if len(item) < len(headers[index]): # A string containing dashes to the length of item[index] or headers[index] # To repeat a character(s), enclose it within quotes followed # by the star sign (*) and the desired number of times. separators = separators + "-" * len(headers[index]) + " " caption = caption + headers[index] + " " values = values + systemInfo[index] + " " * (len(headers[index]) - len(item)) + " " else: separators = separators + "-" * len(item) + " " caption = caption + headers[index] + " " * (len(item) - len(headers[index]) + 1) values = values + item + " " # Increment the value of index by 1 index = index + 1 # End of the loop # Print the variable named caption converted to uppercase print(caption.upper()) # Print separators print(separators) # Print values (items in systemInfo) print(values) # INSTRUCTIONS: # 1) Save the script as uname.py (or another name of your choosing) and give it execute permissions: # chmod +x uname.py # 2) Execute it: # ./uname.py
Once you have saved the above script to a file, give it execute permissions and run it as indicated at the bottom of the code:
# chmod +x uname.py # ./uname.py
If you get the following error while attempting to execute the script:
-bash: ./uname.py: /usr/bin/python3: bad interpreter: No such file or directory
It means you don’t have Python 3 installed. If that is the case, you can either install the package or replace the interpreter line (pay special attention and be very careful if you followed the steps to update the symbolic links to the Python binaries as outlined in the previous article):
which will cause the installed version of Python 2 to execute the script instead.
Note: This script has been tested successfully both in Python 2.x and 3.x.
Although somewhat rudimentary, you can think of this script as a Python module. This means that you can open it in the IDLE (File → Open… → Select file):
A new window will open with the contents of the file. Then go to Run → Run module (or just press F5). The output of the script will be shown in the original shell:
If you want to obtain the same results with a script written purely in Bash, you would need to use a combination of awk, sed, and resort to complex methods to store and retrieve items in a list (not to mention the use of tr to convert lowercase letters to uppercase).
In addition, Python provides portability in that all Linux systems ship with at least one Python version (either 2.x or 3.x, sometimes both). Should you need to rely on a shell to accomplish the same goal, you would need to write different versions of the script based on the shell.
This goes to show that Object Oriented Programming features can become strong allies of system administrators.
Note: You can find this python script (and others) in one of my GitHub repositories.
In this article we have reviewed the concepts of control flow, loops / iteration, and modules in Python. We have shown how to leverage OOP methods and properties in Python to simplify otherwise complex shell scripts.
Do you have any other ideas you would like to test? Go ahead and write your own Python scripts and let us know if you have any questions. Don’t hesitate to drop us a line using the comment form below, and we will get back to you as soon as we can.