CronJob not running
Solution 1:
WTF?! My cronjob doesn't run?!
Here's a checklist guide to debug not running cronjobs:
- Is the Cron daemon running?
- Run
ps ax | grep cron
and look for cron. - Debian:
service cron start
orservice cron restart
- Is cron working?
* * * * * /bin/echo "cron works" >> /tmp/file
- Syntax correct? See below.
- You obviously need to have write access to the file you are redirecting the output to. A unique file name in
/tmp
which does not currently exist should always be writable. - Probably also add
2>&1
to include standard error as well as standard output, or separately output standard error to another file with2>>/tmp/errors
- Is the command working standalone?
- Check if the script has an error, by doing a dry run on the CLI
- When testing your command, test as the user whose crontab you are editing, which might not be your login or root
- Can cron run your job?
- Check
/var/log/cron.log
or/var/log/messages
for errors. - Ubuntu:
grep CRON /var/log/syslog
- Redhat:
/var/log/cron
- Check permissions
- Set executable flag on the command:
chmod +x /var/www/app/cron/do-stuff.php
- If you redirect the output of your command to a file, verify you have permission to write to that file/directory
- Check paths
- Check she-bangs / hashbangs line
- Do not rely on environment variables like
PATH
, as their value will likely not be the same under cron as under an interactive session. See How to get CRON to call in the correct PATHs
- Don't suppress output while debugging
- Commonly used is this suppression:
30 1 * * * command > /dev/null 2>&1
- Re-enable the standard output or standard error message output by removing
>/dev/null 2>&1
altogether; or perhaps redirect to a file in a location where you have write access:>>cron.out 2>&1
will append standard output and standard error tocron.out
in the invoking user's home directory. - If you don't redirect output from a
cron
job, the daemon will try to send you any output or error messages by email. Check your inbox (maybe simplymore $MAIL
if you don't have a mail client). If mail is not available, maybe check for a file nameddead.letter
in your home directory, or system log entries saying that the output was discarded. Especially in the latter case, probably edit the job to add redirection to a file, then wait for the job to run, and examine the log file for error messages or other useful feedback. - If you are trying to figure out why something failed, the error messages will be visible in this file. Read it and understand it.
Still not working? Yikes!
- Raise the cron debug level
- Debian
- in
/etc/default/cron
- set
EXTRA_OPTS="-L 2"
service cron restart
-
tail -f /var/log/syslog
to see the scripts executed
- in
- Ubuntu
- in
/etc/rsyslog.d/50-default.conf
- add or comment out line
cron.* /var/log/cron.log
- reload logger
sudo /etc/init.d/rsyslog restart
- re-run cron
- open
/var/log/cron.log
and look for detailed error output
- in
- Reminder: deactivate log level, when you are done with debugging
- Run cron and check log files again
Cronjob Syntax
# Minute Hour Day of Month Month Day of Week User Command
# (0-59) (0-23) (1-31) (1-12 or Jan-Dec) (0-6 or Sun-Sat)
0 2 * * * root /usr/bin/find
This syntax is only correct for the root
user. Regular user crontab
syntax doesn't have the User field (regular users aren't allowed to run code as any other user);
# Minute Hour Day of Month Month Day of Week Command
# (0-59) (0-23) (1-31) (1-12 or Jan-Dec) (0-6 or Sun-Sat)
0 2 * * * /usr/bin/find
Crontab Commands
-
crontab -l
- Lists all the user's cron tasks.
-
crontab -e
, for a specific user:crontab -e -u agentsmith
- Starts edit session of your crontab file.
- When you exit the editor, the modified crontab is installed automatically.
-
crontab -r
- Removes your crontab entry from the cron spooler, but not from crontab file.
Solution 2:
Another reason crontab will fail: Special handling of the %
character.
From the manual file:
The entire command portion of the line, up to a newline or a
"%" character, will be executed by /bin/sh or by the shell specified
in the SHELL variable of the cronfile. A "%" character in the
command, unless escaped with a backslash (\), will be changed into
newline characters, and all data after the first % will be sent to
the command as standard input.
In my particular case, I was using date --date="7 days ago" "+%Y-%m-%d"
to produce parameters to my script, and it was failing silently. I finally found out what was going on when I checked syslog
and saw my command was truncated at the %
symbol. You need to escape it like this:
date --date="7 days ago" "+\%Y-\%m-\%d"
See here for more details:
http://www.ducea.com/2008/11/12/using-the-character-in-crontab-entries/
Solution 3:
Finally I found the solution. Following is the solution:-
-
Never use relative path in python scripts to be executed via crontab. I did something like this instead:-
import os import sys import time, datetime CLASS_PATH = '/srv/www/live/mainapp/classes' SETTINGS_PATH = '/srv/www/live/foodtrade' sys.path.insert(0, CLASS_PATH) sys.path.insert(1,SETTINGS_PATH) import other_py_files
Never supress the crontab code instead use mailserver and check the mail for the user. That gives clearer insights of what is going.
Solution 4:
I want to add 2 points that I learned:
- Cron config files put in /etc/cron.d/ should not contain a dot (.). Otherwise, it won't be read by cron.
- If the user running your command is not in /etc/shadow. It won't be allowed to schedule cron.
Refs:
- http://manpages.ubuntu.com/manpages/xenial/en/man8/cron.8.html
- https://help.ubuntu.com/community/CronHowto