ulver
ulver

Reputation: 1541

How to test things in crontab

This keeps happening to me all the time: 1) I write a script(ruby, shell, etc). 2) run it, it works. 3) put it in crontab so it runs in a few minutes so I know it runs from there. 4) It doesnt, no error trace, back to step 2 or 3 a 1000 times.

When I ruby script fails in crontab, I can't really know why it fails cause when I pipe output like this:

ruby script.rb >& /path/to/output

I sorta get the output of the script, but I don't get any of the errors from it and I don't get the errors coming from bash (like if ruby is not found or file isn't there)

I have no idea what environmental variables are set and whether or not it's a problem. Turns out that to run a ruby script from crontab you have to export a ton of environment variables.

Is there a way for me to just have crontab run a script as if I ran it myself from my terminal?

When debugging, I have to reset the timer and go back to waiting. Very time consuming.

How to test things in crontab better or avoid these problems?

Upvotes: 9

Views: 3863

Answers (6)

Rob Wells
Rob Wells

Reputation: 37133

G'day,

One of the basic problems with cron is that you get a minimal environment being set by cron. In fact, you only get four env. var's set and they are:

  • SHELL - set to /bin/sh
  • LOGNAME - set to your userid as found in /etc/passwd
  • HOME - set to your home dir. as found in /etc/passwd
  • PATH - set to "/usr/bin:/bin"

That's it.

However, what you can do is take a snapshot of the environment you want and save that to a file.

Now make your cronjob source a trivial shell script that sources this env. file and then executes your Ruby script.

BTW Having a wrapper source a common env. file is an excellent way to enforce a consistent environment for multiple cronjobs. This also enforces the DRY principle because it gives you just one point to update things as required, instead of having to search through a bunch of scripts and search for a specific string if, say, a logging location is changed or a different utility is now being used, e.g. gnutar instead of vanilla tar.

Actually, this technique is used very successfully with The Build Monkey which is used to implement Continuous Integration for a major software project that is common to several major world airlines. 3,500kSLOC being checked out and built several times a day and over 8,000 regression tests run once a day.

HTH

'Avahappy,

Upvotes: 6

glenn jackman
glenn jackman

Reputation: 247022

To find out the environment in which cron runs jobs, add this cron job:

{ echo "\nenv\n" && env|sort ; echo "\nset\n" && set; } | /usr/bin/mailx -s 'my env' [email protected]

Or send the output to a file instead of email.

Upvotes: 2

pgl
pgl

Reputation: 8011

"Is there a way for me to just have crontab run a script as if I ran it myself from my terminal?"

Yes:

bash -li -c /path/to/script

From the man page:

[vindaloo:pgl]:~/p/test $ man bash | grep -A2 -m1 -- -i
   -i        If the -i option is present, the shell is interactive.
   -l        Make bash act as if it had been invoked as a login shell (see
             INVOCATION below).

Upvotes: 7

Marcin
Marcin

Reputation: 3524

Run a 'set' command from inside of the ruby script, fire it from crontab, and you'll see exactly what's set and what's not.

Upvotes: 3

Brian Agnew
Brian Agnew

Reputation: 272337

If you really want to run it as yourself, you may want to invoke ruby from a shell script that sources your .profile/.bashrc etc. That way it'll pull in your environment.

However, the downside is that it's not isolated from your environment, and if you change that, you may find your cron jobs suddenly stop working.

Upvotes: 1

maxwellb
maxwellb

Reputation: 13964

You could write a wrapper script, called for example rbcron, which looks something like:

#!/bin/bash
RUBY=ruby
export VAR1=foo
export VAR2=bar
export VAR3=baz

$RUBY "$*" 2>&1

This will redirect standard error from ruby to the standard output. Then you run rbcron in your cron job, and the standard output contains out+err of ruby, but also the "bash" errors existing from rbcron itself. In your cron entry, redirect 2>&1 > /path/to/output to get output+error messages to go to /path/to/output.

Upvotes: 1

Related Questions