CronProbe Cron Checker

Crontab Traps: Unescaped %, Minimal PATH and Silent Output

CronProbe Guides · Updated 2026-10-31 · All guides

The crontab checker reads every line for the mistakes that cron does not report. These are the ones it looks for.

An unescaped % becomes a newline

In a crontab command, the first unescaped % is turned into a newline and everything after it becomes the command's standard input. So:

30 2 * * * tar czf /tmp/$(date +%F).tgz /data

runs tar czf /tmp/$(date + with the rest as input, and the job fails with a syntax error, usually unseen. Write date +\%F. The checker flags any % not preceded by a backslash.

Minimal environment

Cron starts jobs with a small environment: a short PATH (commonly /usr/bin:/bin), no login profile, HOME and SHELL set by the daemon. A script that relies on /usr/local/bin or on nvm, pyenv or a virtualenv works in your terminal and fails in cron with "command not found". Use absolute paths, or set PATH= at the top of the crontab. The checker notes a command whose first word has no path, and notes when you did set PATH.

Output goes to mail, or nowhere

Anything a job prints is mailed to MAILTO (the user by default). On a host with no mail system that means it is lost; with MAILTO="" it is discarded on purpose. Redirect explicitly, > /var/log/job.log 2>&1, or pipe to logger. The checker flags a job with no redirection and an empty MAILTO.

Overlapping runs

If a run takes longer than the interval, the next starts anyway. Wrap work in flock -n /tmp/job.lock command so a slow run cannot stack against the next one.

Not covered

The checker does not read /etc/cron.d files, which have a user column after the schedule, and it cannot see file ownership or permissions.

Developer Sponsor / Partner
Copied to clipboard!