Sunday, October 21, 2007

This is a question that gets asked by everyone, at some point or another. My script works fine when I run it at the command line, but it never executes correctly when I run it in cron. Why not?

This usually boils down to a few reasons:

1. The cron entry is vague (Cron, at least in the old days) used to be very strict. That is, it ran in a totally different environment than the environment the user had while logged into the shell. It's always good practice to type

* * * * * /usr/bin/lsrather than* * * * * ls

2. That same rule applies for the inside of your scripts. Absolute paths to executables should be used as opposed to just the names of the executables (excluding shell built-ins, of course). So, again:

/bin/grep rather thangrep

3. The easiest way you can make sure that you have same environment in cron as you have when running any script as the regular user is to "source" the environment into the script by adding a line like:

. /etc/profile . /home/user/.profile

to the top of your script (below the #! line). The literal dot, space, filename patterns tells your shell to read in all variables in that named file, so you could run your cron job with the same environment as when you test it manually, which might avoid issues caused by points 1 and 2 above.

4. Finally, some newer versions of cron have configuration files (like /etc/default/cron or /etc/sysconfig/cron) where you can add additional environment variables that you always want set when you run your cron jobs. You can also do this in some newer implementations of cron by adding environment variable lines as the first lines of your crontab. Like:

PATH=/usr/bin:/usr/sbin

If all else fails, points 1 and 2 should almost always fix your problem :)