//

Saturday, February 1, 2014

Python: OS Module

If you are a Linux system administrator, you probably used sometime or may still use, the Python language for your scripts.
If no, you should try it, its really great.

One of the most useful modules Linux sys admins need to be familiar with, is, in my opinion, the OS module.

It basically lets you use operating system functionality within python. You will find many of your daily commands in this module. Like creating directories, change ownership  and killing processes. 
It also OS dependent, so you could use it on other platforms as well.

I will show you few short examples, so you could grasp the idea of it and maybe start using it in your scripts as well.


Note: If you are new to python scripting, make sure that:

1. python installed:
rpm -q python
2. the header of your script should look like:
#!/usr/bin/python
import os
The path of python binary can change, depends on how you installed it. You can verify this by using "which python"

System Information


Lets say your script is used only on 64Bit systems. You could use the OS module in order to perform simple check before you continue to the main function of your program.
print os.uname()[5]
x86_64
os.uname() will return a tuple containing 5 strings. The 4 remaining are:
1 - system name 
2 - hostname
3 - kernel version
4 - release date

It basically has the same functionality as the uname command from the coreutils package.


Files And Directories

Here is an example of how you create a directory:
if not os.path.exists('/tmp/mario'):
        os.mkdir('/tmp/mario')
else:
        print "This directory already exists"
The first line checks whether the directory already exists, if not it will create it using the mkdir function.
Now, would this function work if I'll try to create multiple directories? 
The answer is no. But there is makedirs: 
os.makedirs('/tmp/mario/luigi/and/other/friends')
Now lets rename mario to wario and delete the friends directory
os.rename('/tmp/mario','/tmp/wario')
os.rmdir('/tmp/wario/luigi/and/friends')
The next script will show you how to use the current directory path, list the content of this directory and print the size of the files and directories, using the st_size attribute:
path = os.getcwd()
print "The current directory is %s"%path
for obj in os.listdir(path):
        print "%s size is %s"%(obj, os.stat(path + "/" + obj).st_size)
os.getcwd will get us the current directory path. This is equivalent to the pwd command.
os.listdir will return a list of the directories and files in the current directory. And os.stat will return an object representation of file/directory. This object includes many attributes. One of them is the st_size which represents the file size in bytes.

Prcoess Control

Everyone who uses Linux, at one point or another, interact somehow with processes. You may create one, kill it or pull out some information  you need on specific process.

It may happen, that your script is very important for the system to complete its work cycle. 
You want to ensure its getting the top priority for users processes. How you do it? using nice. or more precisely renice the process of your script.

For everyone who forgot what is renice here is a short reminder: renice is the action of altering the priority of running processes. It can take values from -20 to 19 on most systems. With priority of 19, the process will run only when no other process on the system need to run.

After writing this quite long introduction, here is the short way to do it:
os.nice(-14)
Be aware that this will work as an increment or reduction and as value set.
If your nice value was 2 it will be now -12.

One common task that is used widely by developers and admins is the killing anther process.
This done mostly because of of stuck processes, but sometimes  also because specific conditions are met. 
os.kill(1316, 15)
1316 is the process id. 
15 is the signal. In this case SIGTERM.

Sometimes you'll need to terminate your program because of unexpected behavior. I do it mostly with sys module which is  also an important module. But the OS module also got exit function of its own:
os._exit(2)
This will exit the script with the exit code 2. you can use whatever number you want or need.

Command Execution

In the past, running os.system was a common way for executing commands on your OS with python.
Later, This function was deprecated. So now the best way to execute your own customized command is to use the subprocess module.

Here's a short example of using subprccess to print all SElinux booleans that are on:

import subprocess
subprocess.call('getsebool -a | grep -w on' , shell=True)
You can execute every command you want with subprocess and you can control the way you do it in many ways. I really recommend everyone that still use the system function to stop using it and move to subprocess.
You can find more details on subprocess module right here

The OS module includes many more functions I haven't discussed here. To make the most of this module, check out the full documtion here.
Dont forget, many functions is this module, supported on variety of operating systems.