Cron Script Question

A co-worker is having trouble w/ a job scheduled from cron and I got involved. Unfortunately I couldn't seem to find the answer and need some help. First off, I'm pretty sure he's using redhat linux. Anyway, I want to schedule a cronjob to run a java class. Let's say that, logged in as root, I excute the java class like this...

java MyJavaClass > MyJavaClass.out

This works and the file MyJavaClass.out ALWAYS contains data. In cron I created this entry below to run this command at 5:30AM each day)...

30 5 * * * java MyJavaClass > MyJavaClass.out

HOWEVER, when cron kicks off the job the size of MyJavaClass.out is always 0 bytes. So it looks like the job kicked off at the right time but, for some reason, the call to "java MyJavaClass" didn't execute correctly. My gut feeling is that this is some weird scripting error where the pathing isn't set correctly inside this cron script but I can't figure it out. I've even tried putting in the full path name to the java command (/usr/bin/java or whatever it was) but it still comes back w/ zero bytes. Can anyone explain what's going on to me? Thanks in advance!

The problem seems to be with the location from which cron executes "java MyJavaClass". It seems like the class MyJavaClass.class cannot even be found in the classpath, so the NoClassDefFoundError exception is thrown. There is no output as the error is sent to standard error so your MyJavaClass.out becomes truncated.

What you need to do is to explicitly put a "cd" in the cron line to change the CWD before invoking java, like

cd /some/dir && java MyJavaClass > MyJavaClass.out

You cannot qualify the class with any path, as you probably know, since java expects a class name (optionally with package) as argument which at most only has dots denoting package, not a path with slashes.

Thanks for answering but as is par for the course for me, I have more questions. :slight_smile:

1) The thing that bugs me is that when I run the command "java MyClass" from the command line while logged in as root it runs fine. That means that "MyClass" must be in the CLASSPATH. If so, then I have to assume that the CLASSPATH is changing inside the cron script. I have no idea why though and could sure use an explanation. In fact, I guess I can't be sure that ANY environment variable is what I think it is for that matter. So, it's possible that the PATH variable is set wrong too.

Is there any way to tell what these settings are inside the script? Is the best way to figure that out to write a script that says "env > ~/myEnv" and see what the results are? Or is there a better way?

2) How do I redirect both stdout and stderr of that script to a file? Is it "java MyClass 2&1> ~/myLogfile"? Also, is there any way to put the stdout in one logfile and the stderr in another file?

  1. I think you misunderstood my point. So, have you tried out what I suggested and did that work for you? I think it should, otherwise it may mean you need to explicitly specify the classpath in the java command, which is tedious and I will avoid it if ever possible because, depending on the Java project, missing some Java library class paths that exist in the default classpath will render those libraries unloadable.

No, the Java classpath has not changed. Unless you explicitly specify the classpath, the default classpath used by java ALWAYS contains the current directory (.) that's why if you put a Java class that is not in any package (see Java books for "package" if you don't know what Java packages (i.e. namespaces) are and how they work) in the current directory Java can always find it because . is in the classpath. But when you run it from cron, the current directory is not where your class resides, so it cannot be found. That was the point I would like to make in my previous reply.

PATH has nothing to do with class invocation in java UNLESS you install java in non-standard locations. You can qualify java with absolute path but as you said previously it did not work either. Therefore, it seems like Java can be loaded, it just couldn't find the class. Java doesn't use PATH to do anything internally except from to load the java executable itself.

To same file:
java MyClass >~/myLogfile 2>&1

To different file:
java 1>~/stdout.log 2>~/stderr.log

But if for use with cron, I recommend avoid using ~ but to use absolute paths for filenames.