ShareYourGroupShareYourGroupCron Helper

Cron environment: PATH, shell, MAILTO, % signs and output

A cron job does not run in your terminal. It runs in a small plain environment, and a few characters mean something different there.

The shell and variables

The cron manual says that the command part of a line is run by /bin/sh, or by the shell named in a SHELL variable at the top of the crontab. You can set variables at the top, as the manual's example does:

SHELL=/bin/sh
MAILTO=paul
5 0 * * * $HOME/bin/daily.job >> $HOME/tmp/out 2>&1

A job does not read your .bashrc or .profile, so aliases and a customised PATH are not there. The reliable habit is to give the full path to every program (/usr/bin/python3, not python3) and to the files it uses, or to set PATH yourself at the top of the crontab.

The percent sign

In a crontab line, an unescaped percent sign has a special meaning: the manual says the first one ends the command and everything after it is passed to the command as standard input, and later percent signs become new lines. So the date +%Y-%m-%d that works at the terminal breaks in cron. Write date +\%Y-\%m-\%d.

0 2 * * * tar czf /backups/site-$(date +\%Y-\%m-\%d).tgz /var/www

Output and mail

Whatever the job prints to its output, cron mails to the user (or to the address in MAILTO). A job that prints every minute fills a mailbox, or nothing arrives because the machine has no mail program. The usual cure is to send the output to a file: >> /var/log/job.log 2>&1 appends normal output (1) and error messages (2) to the same log. If you do not need it at all, > /dev/null 2>&1 discards both, but then you will not know when it fails.

The last line needs a newline

The manual's list of caveats says that each entry must end in a newline character. If the last line of the crontab ends without one, cron considers the crontab at least partially broken and writes a warning to the system log. Editors normally add it, but a file made by a script might not.

Permissions

The manual also says crontab files must be regular files, not executable and not writable by anyone but the owner, unless an option overrides it. The scripts you call need to be executable (chmod +x), and the user that cron runs them as needs access to every file they touch.

A debugging trick

Add a line * * * * * date >> /tmp/cron-test.txt and wait two minutes. If the file grows, cron works and the problem is in your command. Remove the line after.

Why does my command work when I paste it into a terminal?

The terminal has your PATH, your aliases and your current folder. Cron has almost none of these.

How do I stop mail from cron?

Set MAILTO="" at the top of the crontab, and write the output of each job to its own log file instead.

This is an independent guide and tool. It is not connected with crontab.guru, Quartz, GitHub, Kubernetes, Spring or the Linux projects named here. Product names belong to their owners.