Friday, August 17, 2012

Debugging Cron Jobs


Just as a reminder, here is the basic script invokation syntax in the crontab table entry:

*=min(0-59) *=hour(0-23) *=monthday(1-31) *=month(1-12) *=weekday(Sunday=0-6) command

[Update 2012-09-03:

First invoke the script in cron from bash embedded via bash -l -c '../my_script.sh', that will make sure cron gives you a realistic bash environment setup, e.g.:

* * * * * /bin/bash -l -c '/home/my_home/bin/my_script.sh'

You can also log all standard and error output in that line by appending .../myscript.sh' > /tmp/my_script.log 2>&1 at the end of the cron entry line.

The bash -l trick did make the difference when setting up the right environment for Ruby scripts that rely on their respective environment to be setup via RVM and their magic usage of the correct bash functions.

This tip is from Andre of the Scoutapp blog.]

Then, if still in cron trouble, put the following at the top of your shell script:

#! /bin/bash

exec &> $HOME/local/var/log/this_script.log

set -x

source $HOME/.bash_profile

env

# script content follows here

---

What does each line do?

- /bin/bash, we have reached 2012, which Unix doesn't doesn't have a bash installed by now?

- exec ... logs standard as well as error output in a file, so you have at least the last run documented (tip by DarkDust).

- set -x prints out all commands in your bash script, lots of information, right?

- ~/.bash_profile invoked in your script sets up your whole environment just like an interactive login shell, at least it should. Make sure you have a sane bash setup script (and whatever is invoked there), make sure you understand all the variations of .profile, .bashrc, or .bash_login or what have you (that's another topic, right?). Test them out so you have little surprises there, don't change directories there or do some other strange side effects. If so, now your cron script should have a very similar environment as when you test out your script from the commmand line.

env can show you what you have in your environment, is the log output the same or different when running the script from the command line? set is another alternative, which also shows all defined functions.


Some questions to ask yourself:

- First, does the script work from the command line?

- Again, does the script have the same environment in cron mode as well as when run from the command line?

- Ok, check the debug output.

- Should I use absolute paths for each and every command invoked in the script, e.g. /usr/local/mysql/bin/mysql instead of just mysql, /bin/grep, or /usr/bin/ruby if you want to go to an extreme. Can be important, if you have and need e.g. a MacPorts command in /opt/local/bin e.g. for the latest getopt command or so.

No comments:

Post a Comment