Prerequisite: Introduction to Linux Shell and Shell Scripting
Linux is one of the most popular operating systems and is a common choice for developers. It is popular because it is open source, it’s free and customizable, it is very robust and adaptable.
An operating system mainly consists of two parts: The kernel and the Shell. The kernel basically handles communication between the software and the hardware. The shell takes inputs or commands from the user and produces an output. Most Linux distributions nowadays use the BASH shell (Bourne again shell). Shell commands and scripts are very powerful and are used commonly by developers.
In this article, we shall look at executing and parsing Linux commands using python.
Subprocess –
Subprocess is a module in Python that allows us to start new applications or processes in Python. This module intends to replace several older modules in python. We can use this module to run other programs or execute Linux commands.
Starting a process –
A new process can be spawned by using the Popen function defined in the subprocess module. It is a constructor for the Popen class that takes arguments to set up the new process. The underlying process creation and management in this module is handled by the Popen class.
Arguments:
- The first parameter is a list that contains the commands and their options if any.
ex:['ls', '-l']
the above example is equivalent to typing ‘ls -l’ in the terminal- The second parameter is the stdout value. it specifies the standard output.
ex:stdout = subprocess.PIPE
This indicates that a new pipe or redirection should be created. The default value is
“None”, which means that no redirection will occur.
We can retrieve the output of a command by using the communicate function. It reads data from stdout and stderr until it reaches the end-of-file and waits for the process to terminate. It returns a tuple that contains the output data and the error if any.
Syntax:
data = subprocess.Popen(['ls', '-l', filename], stdout = subprocess.PIPE)
output = data.communicate()
The output of the executed command is stored in data. Using these functions, we can execute Linux commands and fetch their output.
Listing the directories –
We can use the ‘ls’ command with options such as ‘-l’, ‘-al’, etc to list all the files in the current directory. We can then parse this output and print it in a presentable format. The get_permissions()
function parses the output of the list command and retrieves only the names of the files and their corresponding permissions.
# importing libraries import subprocess import os # a function to list the files in # the current directory and # parse the output. def list_command(args = '-l' ): # the ls command cmd = 'ls' # using the Popen function to execute the # command and store the result in temp. # it returns a tuple that contains the # data and the error if any. temp = subprocess.Popen([cmd, args], stdout = subprocess.PIPE) # we use the communicate function # to fetch the output output = str (temp.communicate()) # splitting the output so that # we can parse them line by line output = output.split( "\n" ) output = output[ 0 ].split( '\\' ) # a variable to store the output res = [] # iterate through the output # line by line for line in output: res.append(line) # print the output for i in range ( 1 , len (res) - 1 ): print (res[i]) return res # parse the output of the ls # command and fetch the permissions # of the files and store them in # a text file . def get_permissions(): # get the output of the # list command res = list_command( '-l' ) permissions = {} # iterate through all the rows # and retrieve the name of the file # and its permission. for i in range ( 1 , len (res) - 1 ): line = res[i] line = line.split( ' ' ) folder_name = line[ len (line) - 1 ] permission_value = line[ 0 ] permissions[folder_name] = permission_value # create a directory called # outputs to store the output files try : os.mkdir( 'outputs' ) except : pass os.chdir( 'outputs' ) # open the output file out = open ( 'permissions.txt' , 'w' ) out.write( 'Folder Name Permissions\n\n' ) # write to the output file for folder in permissions: out.write(folder + ' : ' + permissions[folder] + '\n' ) os.chdir( '..' ) return permissions if __name__ = = '__main__' : list_command( '-al' ) |
Output :
Ping command –
The ping command stands for Packet Internet Groper. It is most commonly used to check the connectivity between two systems or nodes. Using the ping command, we can check whether the connection between one node and another is healthy or not. It exchanges packets of data between two nodes and also calculates the round trip time.
# importing libraries import subprocess import os # a function to ping given host def ping(host): # command is pong cmd = 'ping' # send two packets of data to the host # this is specified by '-c 2' in the # args list temp = subprocess.Popen([cmd, '-c 2' , host], stdout = subprocess.PIPE) # get the output of ping output = str (temp.communicate()) output = output.split( "\n" ) output = output[ 0 ].split( '\\' ) # variable to store the result res = [] for line in output: res.append(line) # print the results print ( 'ping results: ' ) print ( '\n' .join(res[ len (res) - 3 : len (res) - 1 ])) return res if __name__ = = '__main__' : # ping google ping( 'www.google.com' ) |
Output :
Changing permissions –
The chmod
command can be used to change file permissions. It is an abbreviation of change mode. More info can be found here
# importing libraries import subprocess import os # functio to change the permissions # of a given file def change_permissions(args, filename): # command name cmd = 'chmod' # getting the permissions of # the file before chmod ls = 'ls' data = subprocess.Popen([ls, '-l' , filename], stdout = subprocess.PIPE) output = str (data.communicate()) print ( 'file permissions before chmod % s: ' % (args)) print (output) # executing chmod on the specified file temp = subprocess.Popen([cmd, args, filename], stdout = subprocess.PIPE) # getting the permissions of the # file after chmod data = subprocess.Popen([ls, '-l' , filename], stdout = subprocess.PIPE) output = str (data.communicate()) # printing the permissions after chmod print ( 'file permissions after chmod % s: ' % (args)) print (output) if __name__ = = '__main__' : # changing the permissions of 'sample.txt' change_permissions( '755' , 'sample.txt' ) |
Output :