Python for systems administrators – Repetitive tasks

Systems administrators quite often have to perform repetitive tasks on a daily or weekly basis. Whether you are administering users, checking software for python-logoupgrades or performing backups, the less time you spend on boring repetitive tasks the more time you can spend on other important tasks. This is where Python becomes useful, using Python we can develop scripts to group tasks together and decrease the time needed to be spent working on a particular job.

This week I will be using an example scenario of a small company that hosts a large amount of sites. Each week a new site is created and so several tasks need to be performed before the developers can start uploading the site.

I know there are probably many pieces of software out there which can perform these tasks, but this is just purely for demonstration purposes only to show you how Python can help you. If you’re new to Python feel free to ask any questions in the comments section, I would recommend though that you have some experience with Python before you continue to read on.

Below is the list of tasks we need to complete:

Create a new user and set a password

Create a home directory, containing a WWW sub directory

Assign permissions to the directories

Create a database

Assign permissions for the user to access the database

Add a virtual host to the Apache configuration file

I could probably go on but let’s just keep it as simple as possible for now. For someone relatively experienced with Linux, this may take up to 20 minutes to perform all these tasks. But if we use Python we can cut all those tasks down to mere seconds. Let’s take a look at our code below to see how.

{codecitation}import MySQLdb, os, sys

apache = ‘/etc/httpd/conf/httpd.conf’

i = 0

for arg in sys.argv:

if ‘-u’ in arg:

username = str(sys.argv[i+1])

if ‘-p’ in arg:

password = str(sys.argv[i+1])

i+=1

if ( (len(username) < 3) or (len(password) < 6) ):

print “Please enter a valid username or password”

sys.exit()

os.system(‘useradd ‘ + username)

os.system(‘echo “‘ + password + ‘” | passwd –stdin ‘ + username)

os.system(‘mkdir /home/’ + username + ‘/www’)

os.system(‘chmod 755 /home/’ + username + ‘/www’)

os.system(‘chown ‘ + username + ‘ /home/’ + username + ‘/www’)

db = MySQLdb.connect(host=”localhost”, user=”root”, passwd=”password”)

cur = db.cursor()

query = “””CREATE USER ‘{username}’@’localhost’ IDENTIFIED BY ‘{password}’;

CREATE DATABASE {username};

GRANT ALL PRIVILEGES ON {username}.* TO ‘{username}’@’localhost’

WITH GRANT OPTION;”””.format(username=username, password=password)

exec_query = cur.execute(query)

virtualhost = “””

<VirtualHost *:80>

ServerAdmin {username}@example.com

DocumentRoot /home/{username}/www/

ServerName {username}.example.com

ErrorLog logs/{username}-error_log

CustomLog logs/{username}-access_log

</VirtualHost>

“””.format(username=username, password=password)

f = open(apache,”a”)

f.write(virtualhost)

f.close(){/codecitation}

First we can see that I have used 3 different modules, two of which are os and sys. These modules are included in the standard library. However the MySQLdb module is not a part of the standard library so you will need to install it using “yum –y install python-MySQLdb”.

{codecitation}import MySQLdb, os, sys{/codecitation}

Next we take a look a bit further down and you can see that I have used a for statement to iterate all the arguments within sys.arg to look for items or flags containing “–u” or “–p”. You will also probably notice that I have told i to increment for each item in the list, this allows us to determine the item next in line for in the list. For example, if I enter the system arguments –u unixmen, -u would be the first argument and so we know the second argument would be the username.

{codecitation}i = 0

for arg in sys.argv:

if ‘-u’ in arg:

username = str(sys.argv[i+1])

if ‘-p’ in arg:

password = str(sys.argv[i+1])

i+=1{/codecitation}

Next I used the len or length function to determine the length of the username and password. This isn’t required, but its something I thought I would add in to ensure that administrators don’t use weak passwords.

{codecitation}if ( (len(username) < 3) or (len(password) < 6) ):

print “Please enter a valid username or password”

sys.exit(){/codecitation}

If we then take a look further below we can see that I have passed through certain commands to the shell to allow me to create the user, set the password and assign permissions to the www directory. When a user is created by default they are given a directory in the home directory, but we still need a www directory for the website, so a www directory is created with read and execute permissions to group and world. The www will be where the user stores their website files.

{codecitation}os.system(‘useradd ‘ + username)

os.system(‘echo “‘ + password + ‘” | passwd –stdin ‘ + username)

os.system(‘mkdir /home/’ + username + ‘/www’)

os.system(‘chmod 755 /home/’ + username + ‘/www’)

os.system(‘chown ‘ + username + ‘ /home/’ + username + ‘/www’){/codecitation}

Now that we have our user and directories setup, we need to create our user in MySQL, create a database under their name and assign permissions to allow that username to access the database. If you’re not familiar with the MySQLdb function you can find out more here (http://mysql-python.sourceforge.net/MySQLdb.html). Basically we just need to create a cursor to pass our queries through to MySQL. The cursor can also be used to retrieve the output using cur.fetchall().

Note: “Make sure that you modify the password in MySQLdb accordingly to reflect your password for the root user”

{codecitation}db = MySQLdb.connect(host=”localhost”, user=”root”, passwd=”password”)

cur = db.cursor()

query = “””CREATE USER ‘{username}’@’localhost’ IDENTIFIED BY ‘{password}’;

CREATE DATABASE {username};

GRANT ALL PRIVILEGES ON {username}.* TO ‘{username}’@’localhost’

WITH GRANT OPTION;”””.format(username=username, password=password)

exec_query = cur.execute(query){/codecitation}

Finally we create another variable with a literal string and append our virtual host details to the apache configuration file. It is important to only append this file, because if you write to the configuration file you will erase all of the previous data.

{codecitation}virtualhost = “””

<VirtualHost *:80>

ServerAdmin {username}@example.com

DocumentRoot /home/{username}/www/

ServerName {username}.example.com

ErrorLog logs/{username}-error_log

CustomLog logs/{username}-access_log

</VirtualHost>

“””.format(username=username, password=password)

f = open(apache,”a”)

f.write(virtualhost)

f.close(){/codecitation}

If you then run the script using “python script.py –u unixmen –p password” from the command line, or “./script.py –u unixmen –p password” you can now see that all of that work can be completed with only one line, taking only a moment of our time. You will also need to make sure that your script has the appropriate amount of permissions before you run it.

Although this is somewhat of a roughly create script, my hope is that I have shown you a small sample of how powerful Python can be for systems administrators. Feel free to copy it, add to it or give any tips.