I want to test if cron's mailing stuff after an executed task and things like that work. Is there a more elegant way to test this, then setting a cron job to run every few seconds? So, is there any way to simulate the execution of a cron job / start a cron job manually, but with the same behaviour it would have when being run automatically by cron?
-
There is a better solution at http://serverfault.com/q/85893/75968 – cweiske Dec 09 '13 at 07:49
-
This is also discussed on Ask Ubuntu: "Verify if crontab works" – Wildcard Jan 16 '16 at 06:57
3 Answers
The main difference between executing a cron job on the command line and inside cron is its environment. Other potential differences include the current directory, the availability of a terminal, and which shell is used.
This is a fairly accurate simulation of running a cron job via cron. To avoid differences due to the shell, put your job in a script and put only the path to that script in the crontab. Note that the exact set and values of environment variables passed by cron are implementation-dependent; check the crontab(5)
man page on your system. ifne
is a command that runs the command specified in arguments if it receives some input; there's one in moreutils.
env -i HOME="$HOME" LOGNAME="$LOGNAME" PATH=/usr/bin:/bin SHELL=/bin/sh USER="$USER" \
/path/to/script </dev/null 2>&1 |
ifne mail -r "Cron Daemon" -s "Cron <$USER@$(hostname)> /path/to/script" "$USER"
Another way of creating a cron-like setting is through at
. But at
takes care of running the command with the environment variables that the at
process received, so you still need to emulate this part.
echo /path/to/script |
env -i HOME="$HOME" LOGNAME="$LOGNAME" PATH=/usr/bin:/bin SHELL=/bin/sh USER="$USER" \
at now

- 829,060
Here is how I did it to simulate the cron execution of a script I've created years ago but which started failing recently.
I created a script called dumpenv
:
#!/bin/sh
base=$(basename $0)
env -0 > /tmp/$base.$$.dump
This dumps all environment variables into a file in /tmp/
. Then I modified my crontab to add:
*/1 * * * * [path to newly created script]
This makes the script run every minute. So after a minute, I got a dump of the environment seen by tasks run from cron. If the crontab line is left to run more than a minute, it creates a bunch of identical files with names differing only in the pid part of the file name ($$
). No biggie. I could have coded for this eventuality so as to get just one file but the main principle here is "good enough", and I might want to use dumpenv
in other contexts where multiple dumps are useful. At any rate, it is advisable to remove the crontab line that was added so as to avoid populating /tmp
with lots of junk.
Then I created an additional file which I called /tmp/command
which contained the command I wanted to execute, on a single line terminated by a null character. The null character is necessary.
Then I issued:
cat [path to dumpfile crated earlier] /tmp/command | xargs -0 -x env -i
And this replicated the fault I saw when my command is executed from cron. What xargs
does is build an command of the form:
env -i [list of environment variables] [command to execute]
and executes it. The list of environment variables comes from the dump file. The command that env
executes comes from the /tmp/command
file.
The -0
arguments to env
and xargs
and the required null character I mention above is to prevent environment mangling while variables are being passed around. In cases where the environment contains no environment variable with a newline in it, -0
could conceivably be omitted from the invocation of env
in the dumpenv
script and from the xargs
command, and the /tmp/command
file would not require a null character as a line terminator.
I do no explicit redirection of stdin to /dev/null because xargs does it for me. I also do not care about redirecting stdout/stderr, and I do not want to receive an email if the command fails. For cases where these features are desired, Gilles' answer provides the means to do it.

- 160
Louis' answer is great. I propose a slight possible improvement.
Instead of creating a file /tmp/command
which contains the path to the script you want to execute as Louis suggested in the following code:
cat [path to dumpfile crated earlier] /tmp/command | xargs -0 -x env -i
Instead you can name the script directly in the command via the following alternate command (take note of the \x00
appended to the cron script path, which is essential:
printf "/path/to/cron/script\x00" | cat /path/to/dumpfile/created/earlier - | xargs -0 -x env -i
This avoids any need to create a file /tmp/command
.

- 11
-
Note: I edited my original post because I'd found a cleaner solution (using
printf
instead ofawk
) – allnatural Aug 19 '14 at 01:56