People come up with all sorts of debatable shell voodoo for debugging an errant cron job.
If the script runs successfully under your interactive shell, yet fails under cron, I am 99% sure for your case (and 100% sure for my case) that it is due to a difference in runtime environments.
For simple scripts, I’ve had the best luck with simply redirecting all script output to a file. Just add the following lines to the top of the script, set the cron job to run every minute, then inspect the log for failures.
# REDIRECT STDOUT AND STDERR TO LOG FILE exec 1>/home/<username>/cron-debug.txt exec 2>&1
For more involved scripts, it is typically faster to just resolve the env differences up-front instead of tackling each one bug-by-bug minute-by-minute.
1. Find your env command.
> whereis env env: /usr/bin/env /usr/share/man/man1/env.1.gz
2. Save your interactive runtime environment.
> env > /home/<username>/env-runtime.txt
3. Use the paths discovered with whereis to capture cron’s runtime environment.
> crontab -e */2 * * * * /usr/bin/env > /home/<username>/env-cron.txt
4. Wait for env-cron.txt to appear.
5. Compare the text files to see what the cron environment is missing.
> cat /home/<username>/env-cron.txt HOME=/root LOGNAME=root PATH=/usr/bin:/bin LANG=en_US.UTF-8 SHELL=/bin/sh > cat /home/<username>/env-runtime.txt SHELL=/bin/bash TERM=xterm USER=root MAIL=/var/mail/root PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin LANG=en_US.UTF-8 SHLVL=1 HOME=/root LOGNAME=root _=/usr/bin/env OLDPWD=/etc/cron.hourly
6. Supplement the failing script with any paths or variables that are missing from the cron environment.
Other Common Mistakes
- Using the wrong interpreter. (i.e. putting #!/bin/sh at the top of a script that uses bash-specific commands)
- Putting spaces or lines in front of the interpreter line. (i.e. if you are having the shell resolve the script interpreter, it will fail if the #!/<path-to-interpreter> line does not start at row 1, column 1)
- Running as the wrong user. (i.e putting a script that needs root permissions inside an unprivileged user’s crontab)