elidev


Diary of a coder.

Archive for August 30th, 2011

Posted by eli at 30 August , 2011

Today at work I ran into some issues with cron. One of my Java programs would run fine when executing manually, but would throw a ClassNotFoundException for StringBuilder when executing under cron. Since StringBuilder is a somewhat “recent” (haha) addition to the Java API, I suspected that it had to do with crontab running an older version of Java, probably the 1.4.2 version bundled in the Linux dist. I could verify this quickly by adding some debug print to the startup script.

A really nice feature of crontab is that you can set environment variables at the top like this:

SHELL=/bin/bash
JAVA_HOME="/opt/java"
#Minute   Hour   Day   Month   DayOfWeek   Command
* * * * * /path/to/script/script.sh > /path/to/script/log 2>&1

and then just have your script use $JAVA_HOME to locate java. This means that the script can be recycled in different environments with different Java versions.

Of course, even better would be to  not have to wory about $JAVA_HOME at all, and just use the “java” command in the script. This assumes that the java command first found in the path references the correct Java version. In the bash shell this is usually set in the file ~/.bash_profile like this:

JAVA_HOME=/opt/java
PATH=$JAVA_HOME/bin:$PATH
export PATH JAVA_HOME

However, cron does not read these settings, so they must be set up manually in the crontab file according to above. Which was exactly what had been done in my case:

SHELL=/bin/bash
JAVA_HOME="/opt/java"
PATH=$JAVA_HOME/bin:$PATH
#Minute   Hour   Day   Month   DayOfWeek   Command
* * * * * /path/to/script/script.sh > /path/to/script/log 2>&1

and this is where it falls apart. This would be nice if it worked, but it does not. Specifically, the leading lines in the cronab syntax are not a script, just a collection of name-value assignments. This means that the expansion of $PATH and $JAVA_HOME fails in the example above. To remedy this you have to repeat the JAVA_HOME variable in the PATH assignment, and also make sure to include everything else of interest, which means you need to do something like this:

SHELL=/bin/bash
JAVA_HOME="/opt/java"
PATH=/opt/java/bin:/sbin:/bin:/usr/sbin:/usr/bin
#Minute   Hour   Day   Month   DayOfWeek   Command
* * * * * /path/to/script/script.sh > /path/to/script/log 2>&1

Of course, this is all detailed in the manual for crontab. It still took me some time (and help) to fully diagnose the error (mostly due to the fact that I missed that the debug print of the $PATH variable did not expand $JAVA_HOME).

Tags: ,
Posted in: Uncategorized | No Comments »