views:

671

answers:

5

I have a perl script (part of the XMLTV family of "grabbers", specifically tv_grab_oztivo).

I can successfully run it like this:

/sw/bin/perl /path/to/tv_grab_oztivo --output /path/to/tv.xml

I use the full paths to everything to eliminate issues with the Working Directory. Permissions shouldn't be a problem.

So, if I run it from the Terminal (Mac OSX) it works just fine.

But when I set it to run via a cron job, nothing appears to happen at all. No output is created etc.

There isn't anything wrong with the crontab as far as I can see, because if I substitute a helloworld.pl for the actual script, it runs just fine at the right time.

So, what can I do to debug? I can see from looking at %ENV in the two cases that the environment is very different, but what other approaches can I take to debugging? How can I see the output of the cron job, which might be some kind of perl "die" message or "not found" message from the shell or whatever?

Or should I be trying to somehow give the cron version of the command the same environment as when it's running as me?

A: 

cron usually captures the output of stdout and stderr and e-mailes any output to the crontab owner.

Did you double check your crontab entry to make sure it's valid and will execute at the right time?

Make sure that the script does not need any environment variables set. Otherwise wrap it in another (bash) script, where you can set the environment variables that the other script expects.

lothar
"Did you double check your crontab entry to make sure it's valid and will execute at the right time?" -- Yes. I said so.
AmbroseChapel
Never mind, I just wanted to double check, too. The crontab syntax is tricky and it's easy to get it wrong.
lothar
+5  A: 

It's often because you don't get the full environment when running under cron. Best bet is to capture the ouput by using the command:

( /sw/bin/perl /path/to/tv_grab_oztivo ... ) >/tmp/qq 2>&1

and then have a look at /tmp/qq.

If it does turn out to be a missing environment, then you may need to put:

. ~/.profile

or something similar, into the execution chain of your cron job, such as:

( . ~/.profile ; /sw/bin/perl /path/to/tv_grab_oztivo ... ) >/tmp/qq 2>&1
paxdiablo
It's working. Thank you. In the end I just added the PERL5LIB and PATH to $ENV and all was well.
AmbroseChapel
+2  A: 

If you're looking at %ENV in the two cases, I'd suggest that, as a first step in your perl script, set %ENV to what it is in a cron job, and then trying to run it from the command line. You may need to exec yourself once for this to take full control:

BEGIN {
  if (exists $ENV{something_in_your_env_not_in_cron}) {
     %ENV = (...);
     exec $^X, $0, @ARGV;
  }
}

Now try running it, and seeing if there's anything you can do to debug it (including running under perl -d if required). Most likely, you'll find that you end up adding items back into %ENV one at a time until it magically starts working (LD_LIBRARY_PATH is a good one for this, but ORACLE_HOME or DB2HOME for Oracle or DB2 apps might be good choices, too). Then you can either set the variable in your script, or in the crontab.

Tanktalus
Thank you for your help with this, you're really equal with Pax in helping me but I can only give one Correct Answer, sorry.
AmbroseChapel
A: 

I'd run a simple shell script by absolute path from the cron command. Inside that script, I'd ensure that I trapped stdout and stderr to a known (or knowable) file. I'd also ensure that enough of your environment is set. On Unix, you get almost no environment set at all when you run a command via cron - I'm not sure about MacOS X. The standard culprit for problems is PATH. I have a separate .cronfile that sets my working environment enough that I usually don't have problems - that's an analogue of .profile.

Jonathan Leffler
A: 

On occasion if you can't figure out what's going wrong with your command line, the simplest way to fix it is to turn the whole thing into a shell script. Ideally you shouldn't have to do this, but it can be the fastest way to solve the problem.

File: /files/cron1.sh

#!/bin/sh
/sw/bin/perl /path/to/tv_grab_oztivo --output /path/to/tv.xml

And then in cron:

/files/cron1.sh

This allows you to test the script independent of cron. Remember though that your login shell runs with different environment variables than cron does.

tylerl