Setting up CRON via a python script without using external library

What is the best tool in computer that can do your job automatically and is something which otherwise, if not there would involve manual intervention?

Life around computer is increasingly getting more complex with our lifestyle demanding more of automated work. Out of philosphy let's face it, we need tools that we can set up for doing tasks for us, run scripts for us whenever we want.

When it comes to schedulers, it's like an alarm clock or a timer which goes of for whatever time we set it and then ensure we do our tasks.

Now, in the world of Linux, we know this schedulers at system level as Cron.

Cron is a system daemon which is used to execute desrired tasks (in the background) at specific designated time. It is used to schedule jobs (commands or shell scripts) to run periodically at fixed times, dates, or intervals. It typically automates system maintenance or administration

Now, thinking of cron, it's a name we use, when we have to schedule a task. Now, I am referring to a linux machine with Ubuntu flavor (Pretty much would be same across for other linux distributions).
Crontab is a cron file which can be used to express jobs or tasks in the form of scripts to be executed.

Checkout man cron and man 5 crontab. You would find loads of information about the same.

Let's being.

Python has many frameworks, and libraries which help us setup the cron:
  https://pypi.python.org/pypi/python-crontab
  https://github.com/kraiz/django-crontab
  https://apscheduler.readthedocs.org/en/latest/

Now, my duty was to not to use any external library because "It was told to me" !!! (Hard reality of Job :P).

Crontab Sections
Each of the sections is separated by a space, with the final section having one or more spaces in it.
No spaces are allowed within Sections 1-5, only between them.
Sections 1-5 are used to indicate when and how often you want the task to be executed.
This is how a cron job is laid out: minute (0-59), hour (0-23, 0 = midnight), day (1-31), month (1-12), weekday (0-6, 0 = Sunday)

Learn more from: https://help.ubuntu.com/community/CronHowto

Just to know: LD_LIBRARY_PATH is used by your program to search for directories containing the libraries after it has been successfully compiled and linked. Like a library required for your program. In my case, cx_Orcle needed the oracle libraies installed.

When we see a system crontab, the PATH and LD_LIBRARY_PATH are automatically present.

In case of user crontab, we might have to provide the linkages.

#!/usr/bin/python2.7

import sys
import subprocess
import shlex
import os

CURRENT_FILE_DIR = os.path.dirname(os.path.abspath(__file__))
STARTUP_FILE = os.path.join(CURRENT_FILE_DIR, "check_status.py")

# COMMAND to execute
EXECUTION_CMD = 'python {0}'.format(STARTUP_FILE)

# CRON value to add (at 3 in the morning).
CRON_VALUE = '{0} {1}'.format("0 3 * * *", EXECUTION_CMD)

# Store the system PATH as a key value in a string format
# So that the crontab knows the "python" lives in the PATH defined. 
PATH_VALUE = 'PATH={0}'.format(os.environ.get("PATH", ''))

# LD_LIBRARY_PATH is used by your program to search for directories containing the 
# libraries after it has been successfully compiled and linked.
LD_LIBRARY_PATH = "LD_LIBRARY_PATH={0}".format(os.environ.get("LD_LIBRARY_PATH")) if os.environ.get("LD_LIBRARY_PATH") else ''

print "The cron job to be created is: {0}.".format(CRON_VALUE)

# Provides a list of existing cron's if any
command_1 = 'crontab -l'
proc_1 = subprocess.Popen(shlex.split(command_1), stdout=subprocess.PIPE,  stderr=subprocess.PIPE)

# Below proc_1.communicate() gives tuple as:
# (In case there was never a crontab created)
# ('', 'no crontab for user11\n')
# In case there was a crontab created but has no entries
# ('', '')
# In case there was a crontab created with "0 3 * * * test.py" expression
# ('0 3 * * * test.py\n', '')
# In case there were multiple expressions are created out, err = proc_1.communicate()
# ('0 4 * * * test.py\n0 3 * * * script.py\n', '')


if out is not "":
    new_value = [item for item in out.split("\n") if not EXECUTION_CMD in item and item.strip() != "" and 
                              not ("PATH" in item or "LD_LIBRARY_PATH" in item)]
    # First add the LD_LIBRARY_PATH ensuring its the second command after PATH
    new_value.insert(0, LD_LIBRARY_PATH)
    new_value.insert(0, PATH_VALUE)
    new_value.append(CRON_VALUE)
    value = '\n'.join(new_value)
else:
    value = '{0}\n{1}\n{2}'.format(PATH_VALUE, LD_LIBRARY_PATH, CRON_VALUE)

# Option -e reads backslash and hence can add "\n" to crontab, making it a new line
command_2 = "echo -e '{0}'".format(value)

proc_2 = subprocess.Popen(shlex.split(command_2), stdout=subprocess.PIPE)

command_3 = 'crontab -'
# Notice the stdin for proc_3 is proc_2.stdout
proc_3 = subprocess.Popen(shlex.split(command_3), stdin=proc_2.stdout, stdout=subprocess.PIPE)

# proc_2 and proc_3 act like a pipe line as follows:
# echo -e '0 3 * * * check_status.py' | crontab -
# Now the above line echo's the data to crontab via pipe and reloads it.

out, error = proc_3.communicate()

proc_1.stdout.close()
proc_2.stdout.close()

if error != '':  # If there were errors, like: "-":1: bad minute
    sys.exit(error)

print 'Done, with crontab guys. Now relax :)'

Note: Give the executable permission to the script you want to be executed.
 
sudo chmod +x /path/to/script/check_status.py

The Github Repo where you would find it: https://github.com/tan31989/PythonCron

Comments

  1. Your Blog is amazing. If you want to know that HOW TO SETUP A CRON JOB then,
    Click here for more information:
    HOW TO SETUP A CRON JOB

    ReplyDelete

Post a Comment

Popular posts from this blog

SSH using Chrome Secure Shell app with SSH identity (private key and public key)

Load Testing using Apache Bench - Post JSON API

NGinx + Gunicorn + Flask-SocketIO based deployment.