5

I've got a python script that I want to run via crontab. My crontab looks like this:

5,20,35,50 * * * * /var/www/django-apps/callreport/util.py

That script is set up to parse a bunch of flat files and stick the info into a MySQL db, then delete the files. It runs fine from the command line, data is copied to the db, and the flat files are removed. But nothing happens when set to run as a cron job.

In the past, I'd get a mail message when a cron job failed, but I'm not getting any feedback with this one, and I'm still feeling my way through being a sysadmin on this box. What am I doing wrong?

11 Answers 11

12

The usual problem with 'cron' jobs is that they have zero environment - unlike 'at' jobs which do copy your environment. When something works from the command line and not from 'cron', my experience is that 'environment' is one of the most common problems. Occasionally you run into another problem - 'cron' jobs are not run with a terminal, and occasionally programs get stroppy about this. However, this is in the 1% range compared with 99% for environment issues.

The other key technique I use is to always run a shell script from 'cron'; the shell script ensures that the environment is set correctly and then runs the real program. If a 'cron' job is giving me problems, I can then tweak the script to do useful things like this:

{
    date
    env | sort
    set -x
    ...what was there before adding the debug...
} >/tmp/cron.jobname.$$ 2>&1

This redirects all the output - standard output and standard error - to a file name. You can build timestamps into the filename if you prefer that to the process ID. Analyzing the log files often reveals the problems swiftly.

2
  • 1
    The problem was the environment. Part of my script was relying on a path relative to the current working directory. When run as a standalone script from the command line, this wasn't a problem, but cron's current working dir was my home directory (this was my user crontab). Fixing the script to work out the right path solved my problem. Oct 27, 2009 at 19:00
  • 1
    Thanks so much for this! Using this, turned out that my problem was also related to the environment. I didn't think it was because at the beginning of my shell script I had source $HOME/.bashrc and I was scratching my head what was wrong. I realized the check at beginning of .bashrc was to not do anything if the shell is not an interactive one. I sourced the correct file and now my cron job runs!
    – Maghoumi
    Feb 23, 2020 at 17:55
2

First, just check that crond is running.

When cronjobs that work on the commandline fail to run as expected, it's usually an environment problem for me -- remember that the cronjob will not be running as an interactive shell.

From your commandline, run env(1) and copy these down somewhere. Next, modify your cronjob to run env so you can compare the values. Cron should email you the output (you said it was before); HD mentioned how to configure this.

5,20,35,50 * * * * env; /var/www/django-apps/callreport/util.py
2

These are some ideas for troubleshooting your problem:

  • Check your system logs to see if the cron daemon is actually launching the script
  • If your jobs are not being logged, try increasing the logging level so that you that cron logs the start of each job (see man cron). For example, if you are running the Vixie cron daemon, this can be done by specifying the -L 1 option (or -L 2 if you also want to check when your job finishes).
  • From your Python script, as soon as it starts, create an empty file on the /tmp directory (this is another way to help you verify that the script is being called by cron and it's starting without problems)
2

whereis python

output should be...

/usr/bin/python

then the full path to python before the script.

5,20,35,50 * * * * /usr/bin/python /var/www/django-apps/callreport/util.py

1
  • Yes. Python could be specified in your environment via your rc. An absolute declaration like egorgy says, or an absolute path declaration in your script may help. Sep 6, 2009 at 23:56
0

I think you can redirect the output of the command to a file to see why it is failing, something like

/var/www/django-apps/callreport/util.py > /tmp/util_log.txt

most of the cases which i have seen for silent failure are because the script could not be executed and not an issue with the script itself

1
  • Redirecting the output did nothing; didn't even generate the log file. It appears that my cron job isn't running at all. Aug 18, 2009 at 16:41
0

You can put this line at the top of your crontab:

MAILTO="[email protected]"

To receive a mail from cron. Also you can redirect the output to a temporary fail as Dinesh Manne says to check what happened to your command. Just asking: are you sure that you're using the user which is running the command is the same as the owner of the crontab you're editing?

1
  • added the MAILTO line, but received nothing. And I'm certain that the file ownership/permissions match the owner of the crontab. Aug 18, 2009 at 16:58
0

Be absolutely sure that your crond runs scripts with a dot in the filename...!

0

Also - verify your user is not in the cron.deny file. If you only want cron to run for certain folks, add your user to cron.allow.

0

Force it to crash. Put something wrong instead of #!/usr/bin/python and verify if you get an error report by e-mail - you should set the MAILTO variable to your e-mail address. But check first if the scripts really fails if you ran it from command line. If you still don't get an e-mail error verify if some e-mails are stucked in the local mail queue (mailq). Maybe this will help figuring out about the silent failure.

Also, on what internal systems does this script depends ? DNS, ldap/nis ? Does it have any hardcoded IP addresses or hostnames that no longer exists (i.e. mysql host) ? Can you correlate the last time it succefully ran with the last change done to the script ? Did someone did a stealth upgrade to python on your machine ? Do you have sufficient disk space and indoes (df -i ) ?

Do you have an empty line at the end of you crontab file ? If you force the script to run as root (bad, use it only for testing) does it work ?

0

Do you have this job in a user's crontab (Can you see it with crontab -l?) or is it in the system crontab (/etc/crontab)? The system crontab (On linux at least, don't know about other systems) requires an additional user argument that the user crontabs do not.

In a user specific crontab, it should look like:

# crontab -l
...
5,20,35,50 * * * * /var/www/django-apps/callreport/util.py

Whereas the same command in the system crontab should look like:

# cat /etc/crontab
...
5,20,35,50 * * * * www-data /var/www/django-apps/callreport/util.py

The user might be different on your system of course but that's the general idea.

1
  • It's in a user crontab. Oct 26, 2009 at 23:29
0

It sounds like you've already checked, but double check that the script is being run as the correct user. When I troubleshoot cron jobs, I like to use (on my mac) system calls using the say command so that I hear the parameters I'm interested in. So I might add to util.py the following:

import os
os.system('whoami')

Other than that, I'd put my money on a permission issue; your cron job may not be able to do the things you ask because permissions aren't letting it.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .