Cron tools › Explain / Test
Crontab checker
Why isn't my cron job running? Most of the time it is something in the crontab file itself — an unescaped
%, Windows line endings, a missing last newline, a schedule that never fires. Check the whole file at once and get
a corrected copy.
Findings
Fixed crontab
Only mechanical fixes are applied: LF line endings, a final newline, no byte-order mark, and every unescaped
% in a command written as \%. Everything else is left for you to decide. The download is saved with LF endings.
How to check a crontab
- Open the crontab file with Open file… or drop it on the box — or paste
crontab -loutput. Opening the file lets the checker see CRLF line endings and whether the last line ends with a newline. - Choose the Format: a user crontab, or a system crontab (
/etc/crontab,/etc/cron.d/*) with a user name between the schedule and the command. - Pick the Time zone the machine runs in, so jobs scheduled inside a daylight-saving change are found. A
CRON_TZ=line in the file overrides it for the lines after it. - Work through the findings by line number: errors first, then warnings, then notes.
- Copy or download the fixed crontab, review it, and install it with
crontab file.
What the checks look for
| Check | Why it matters |
|---|---|
Unescaped % | cron turns % into a newline and sends everything after the first one to the command as standard input, so date +%F never gets its format. Write \%. |
| Missing final newline | crontab(5): each entry must end in a newline; if the last one does not, cron considers the crontab (at least partially) broken. |
| CRLF line endings | cron ends an entry at the newline; the carriage return in front of it stays on the line, at the end of the command or value. |
| Schedule errors and warnings | Each schedule is parsed as Vixie cron / cronie would: out-of-range values, * 9 * * * running 60 times, uneven steps, day-of-month OR day-of-week, days that never occur. |
| Never runs | 0 0 31 2 * is valid syntax but no date matches it. |
| Jobs in DST hours | A fixed-time job in a skipped hour runs right after the jump; in a repeated hour it runs once (cronie cron(8)). |
| Comment after a command | crontab(5) does not allow a comment on the same line as a command or an environment setting. |
2>&1 >> file | Redirections apply left to right, so errors go to cron's mail and only output reaches the file. |
| No redirection | Whatever the command prints is mailed to MAILTO. |
| Bare command names | cron's default PATH is minimal, so a command your shell finds may not be found by cron. |
| Curly quotes, odd dashes, non-breaking spaces | Copied from documents; the shell treats them as ordinary characters. |
Duplicates, @reboot, ~ | A duplicate line runs twice; @reboot runs when the cron daemon starts, possibly before other services; 6~15 is cronie's random value. |
User crontab or system crontab?
A user crontab — the one crontab -e edits — has five time fields and then the command. /etc/crontab and
the files in /etc/cron.d have a sixth field, the user the command runs as, before the command. Checking one format
as the other shifts every field by one, so the checker points out lines that look like the other format: a user crontab line
whose command starts with root, or a system line whose "user" is a path. To see a crontab as a table with the next
run of every line, use the crontab viewer; to build a new line with % escaped and
logging set up, use the crontab line builder.
FAQ
My job runs from the shell but not from cron. What should I check first?
Three things cause most of it: a % in the command (cron cuts the command there), a command cron cannot find because
its default PATH is minimal (use full paths), and output you never see because it is mailed to MAILTO rather than printed. The
checker flags all three.
Why is the missing newline only an error when I open the file?
Pasted text rarely keeps the final newline, so the checker cannot tell whether your file has one. Opening the file reads the exact bytes; then a missing newline after the last entry is reported as the error it is.
Does it understand CRON_TZ and cronie's ~ syntax?
Yes. CRON_TZ= is a cronie setting that sets the zone the entries are scheduled in; the DST check uses it for the lines
after it. 6~15 is cronie's random value, picked when the crontab is parsed; those lines are checked for syntax, but
their run times cannot be known in advance.
Is my crontab uploaded anywhere?
No. The file is read by this page's JavaScript and never leaves your browser, and — unlike the other tools here — nothing about it is put in the address bar, since crontabs often hold paths, hosts and addresses.