Why crontab scripts are not working?
Different environment
Cron passes a minimal set of environment variables to your jobs. To see the difference, add a dummy job like this:
* * * * * env > /tmp/env.output
Wait for /tmp/env.output
to be created, then remove the job again. Now compare the contents of /tmp/env.output
with the output of env
run in your regular terminal.
A common "gotcha" here is the PATH
environment variable being different. Maybe your cron script uses the command somecommand
found in /opt/someApp/bin
, which you've added to PATH
in /etc/environment
? cron ignores PATH
from that file, so runnning somecommand
from your script will fail when run with cron, but work when run in a terminal. It's worth noting that variables from /etc/environment
will be passed on to cron jobs, just not the variables cron specifically sets itself, such as PATH
.
To get around that, just set your own PATH
variable at the top of the script. E.g.
#!/bin/bash
PATH=/opt/someApp/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# rest of script follows
Some prefer to just use absolute paths to all the commands instead. I recommend against that. Consider what happens if you want to run your script on a different system, and on that system, the command is in /opt/someAppv2.2/bin
instead. You'd have to go through the whole script replacing /opt/someApp/bin
with /opt/someAppv2.2/bin
instead of just doing a small edit on the first line of the script.
You can also set the PATH variable in the crontab file, which will apply to all cron jobs. E.g.
PATH=/opt/someApp/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
15 1 * * * backupscript --incremental /home /root
My top gotcha: If you forget to add a newline at the end of the crontab
file. In other words, the crontab file should end with an empty line.
Below is the relevant section in the man pages for this issue (man crontab
then skip to the end):
Although cron requires that each entry in a crontab end in a newline
character, neither the crontab command nor the cron daemon will detect
this error. Instead, the crontab will appear to load normally. However,
the command will never run. The best choice is to ensure that your
crontab has a blank line at the end.
4th Berkeley Distribution 29 December 1993 CRONTAB(1)
Cron daemon is not running. I really screwed up with this some months ago.
Type:
pgrep cron
If you see no number (i.e. cron's main PID), then cron is not running. sudo /etc/init.d/cron start
can be used to start cron.
EDIT: Rather than invoking init scripts through /etc/init.d, use the service utility, e.g.
sudo service cron start
EDIT: Also you could use systemctl in modern Linux, e.g.
sudo systemctl start cron
The script filenames in cron.d/
, cron.daily/
, cron.hourly/
, etc., should not contain dot (.
), otherwise run-parts will skip them.
See run-parts(8):
If neither the --lsbsysinit option nor the --regex option is given then
the names must consist entirely of upper and lower case letters, dig‐
its, underscores, and hyphens.
If the --lsbsysinit option is given, then the names must not end in
.dpkg-old or .dpkg-dist or .dpkg-new or .dpkg-tmp, and must belong to
one or more of the following namespaces: the LANANA-assigned namespace
(^[a-z0-9]+$); the LSB hierarchical and reserved namespaces
(^_?([a-z0-9_.]+-)+[a-z0-9]+$); and the Debian cron script namespace
(^[a-zA-Z0-9_-]+$).
So, if you have a cron script backup.sh
, analyze-logs.pl
in cron.daily/
directory, you'd best to remove the extension names.