Troubleshooting cronjobs using an interactive shell

One of the most common little annoyances on Linux machines is troubleshooting cronjobs. You write a little script that you want to be run from cron and you test it extensively on you command line. Once the script runs flawlessly you schedule it to run somewhere during the night, only to find out the next morning that nothing happened.

Puzzled by why nothing happened you start running the script from the command line where, of course, all works fine. Searching for the problem you realize the environment when run from cron must be different from your normal shell. You start running the job from cron, adding debugging messages, redirecting the errors to a temporary file, and reconfiguring the crontab to run the job in one or two minutes … and again in one or two minutes … and again in one or two minutes … . Step by step every little (usually PATH-related) problem is solved by manually rescheduling the job. Struggling to find more details, waiting for cron to re-run the job, it can take a long time to solve all issues with the script.

If only you were able to run an interactive shell with an environment set identical as if it was run from cron! The script below does exactly that. It sets an excellent environment to debug scripts that are required to run from cron. It allows you to execute individual commands and inspect its result one by one, just like you would troubleshoot a regular shell script. No more waiting for cron to fire the job only find out you still overlooked another little issue.

The ‘cronShell.sh’ script below is an optimized version that can be directly used on most Linux machines. It automatically adapts for the current user.

#!/bin/bash

# This script starts a shell with an environment that has
# identical environment as a shell script started from cron.

# More info: https://blog.linformatronics.nl/16/linux/troubleshooting−cronjobs

user=$( id -nu )

cd && env -i sh -c "
### Ubuntu Linux 12.10
export HOME='${HOME}'
export LANG='en_US.UTF−8'
export LANGUAGE='en_US:en'
export LOGNAME='${user}'
export PATH='/usr/bin:/bin'
export PWD='${HOME}'
export SHELL='/bin/sh'
###
exec sh"

And this is what it looks like when you run the script:

jhendrix@diablo:~$ cronShell.sh
$ set
HOME='/home/jhendrix'
IFS='
'
LANG='en_US.UTF−8'
LANGUAGE='en_US:en'
LOGNAME='jhendrix'
OPTIND='1'
PATH='/usr/bin:/bin'
PPID='32184'
PS1='$ '
PS2='> '
PS4='+ '
PWD='/home/jhendrix'
SHELL='/bin/sh'
$ # Type your commands here ...

Credit where credit is due: This post is heavily inspired on an excellent answer by Stephane Chazelas on Unix.StackExchange.com.