Monday, June 27, 2011

Shell Trick: cron script indirection

The Problem

When you add crontab entries, it is easy to forget that they will be executed in a different environment than your usual shell. None of the settings from your .bashrc will be available. The environment will not be empty, but it will be pretty bare. If your command depends on any of these settings, the will fail. The different environment also makes it trick to test. You might end up with a long, complicated one-line command that is hard to maintain.

The Solution

One solution is to use the 'env' command to explicitly build the environment for your command. This can work, but it can make your entry very long and hard to read (and thus hard to test/debug/maintain).

My favored approach is to make all crontab entries simply invoke a script that defines all the settings and then invokes the desired command. I create the directory ${HOME}/shrawenv to hold all these scripts. (I chose this name to denote "for shell with raw environment".)

For example, I would have a crontab entry like
00 5 * * * sh /home/user/shrawenv/
Then I would define the '' script as

export APP_HOME=/usr/share/app-1.1
export SOME_LIB=/usr/share/lib-2.3
$APP_HOME/bin/projectApp arg1 arg2
This dummy example merely demonstrates how to set environment variables before invoking a command. It is a good idea to always use full paths in crontab because PATH may not be what you are used to.

In my crontab, all the commands are just invoking scripts from shrawenv. I want to to list only a simple command and the time of execution. I find it much cleaner to have all the details of the command separately in the script file.

Note that shrawenv is useful not just for cron, but for other contexts where execution is not happening in the usual shell command line. I also use it to house scripts to be called by desktop launchers.

Because this is a script file, it can edited and formated for elegance. Using 'env' would force it all into one line, and may require some syntactic gymnastics.

If I have to make any adjustments to the logic, I do not edit the crontab. Instead I just modify the internals of the script as needed.

You do not have to wait for cron to run to see what the script does. You can simply execute the script. There is an explanation of how to simulate the cron environment here.

I keep my shrawenv under revision control. (I use subversion locally.) If I took the approach of putting all the logic in the crontab, I would not have any history.

No comments:

Post a Comment