← All 93 books cron, one lesson per page Get the full edition · £10
One lesson per page

cron, one lesson per page

Twenty-nine lessons for scheduling on Linux and Unix: how crontab's five fields really match, the DOM/DOW OR rule that surprises everyone, ranges, lists and step values, the special @ strings, the environment every job runs in (a sparse PATH and /bin/sh), why a job runs in your terminal but never under cron, the % that becomes a newline, cron.d files, anacron for machines that sleep, the cron.deny and cron.allow gates, and the logging and mail habits that show what actually ran.


Steve Hodgkiss 6 lessons

A diagram, the schedule, and one thing to try this week. That's a page.

cron, one lesson per page

Twenty-nine lessons for scheduling on Linux and Unix: how crontab's five fields really match, the DOM/DOW OR rule that surprises everyone, ranges, lists and step values, the special @ strings, the environment every job runs in (a sparse PATH and /bin/sh), why a job runs in your terminal but never under cron, the % that becomes a newline, cron.d files, anacron for machines that sleep, the cron.deny and cron.allow gates, and the logging and mail habits that show what actually ran.


Set in Space Grotesk, Inter and JetBrains Mono (SIL Open Font License).

Every fact in this book is as the official sources state it, fetched and read during this build: the crontab(5), cron(8) and crontab(1) man pages hosted at man7.org (the cronie crond project), the Debian crontab(5) man page (classic Vixie lineage), and the Debian anacron(8) and anacrontab(5) man pages. The Wikipedia crontab article was read for orientation only and no facts are sourced from it. cronie-specific extensions are labelled as the sources label them. Demand evidence from live beginner threads, reconfirmed at dispatch; no facts are sourced from Reddit or StackExchange. An independent guide, not affiliated with or endorsed by the cronie project or the Debian Project.

Your purchase is for personal use only. You do not have redistribution rights: please do not share, resell, or republish this book or its pages.

© 2026 Steve Hodgkiss. All rights reserved. Personal use only; no redistribution rights.

Edition 1.0 · stevehodgkiss.net

Contents

Contents


Part 1 · The line4
Five fields, one line5
The OR rule6
Part 2 · Runs as
A sparse PATH7
Part 3 · System jobs8
Where jobs live9
Jobs in /etc/cron.d10
Part 4 · Real work
One habit to keep11
Part 1 of 4
what a crontab is
1

The line

The five time-and-date fields and the command, checked once a minute; asterisks, ranges, lists and steps; the OR rule for the two day fields; names and the @ special strings.


In this part
  1. 01Five fields, one line
  2. 02The OR rule

Per crontab(5): each line has five time-and-date fields followed by a username (if this is the system crontab file) and followed by a command; commands are executed by cron(8) when the minute, hour and month of year fields match the current time and at least one of the two day fields (day of month, or day of week) matches the current time; cron(8) examines cron entries every minute; the fields are minute 0-59, hour 0-23, day of month 1-31, month 1-12 (or names), day of week 0-7 (0 or 7 is Sunday, or use names).

build and run · No. 01
The line

Five fields, one line

The shape of a job

five time fields decide; the rest of the line is the commandminute30hour4day of month*month*day of week*the commandbackupthe system crontab adds one more field:userbetween the five and the commandchecked once a minuteno seconds, no years: the minute is the finest grain cron seeslearn the five slots and you can read any crontab on any machine

Every job is one line: five time fields, then the command. Minute, hour, day of month, month, day of week. In the system crontab a username sits between the fields and the command.

cron wakes once every minute and runs the command when the minute, hour and month match and at least one of the two day fields matches. Nothing else exists: no seconds, no years.

Learn the five slots and you can read any crontab on any machine.

TRY IT THIS WEEK

Write one line this week, 30 4 * * * in front of a command you can see happen, and watch it fire at 4:30 in the morning.

Per crontab(5), Note: the day of a command's execution can be specified by two fields, day of month and day of week; if both fields are restricted (i.e. do not contain the * character), the command will be run when either field matches the current time; for example 30 4 1,15 * 5 would cause a command to be run at 4:30 am on the 1st and 15th of each month, plus every Friday.

build and run · No. 02
The line

The OR rule

Two days, one OR

two restricted day fields OR, they never AND30 4 1,15 * 54:30am1st and 15thmonth freeFridays too12345678910111213141516171819202122232425262728amber: day of month matchedteal: every Fridayboth fire, no overlap neededpeople expect AND. cron says ORwant AND? test the date in the commandboth day fields without a star runs when either matches

The trap behind every scheduler question: when both day fields are restricted, no asterisk in either, cron ORs them. 30 4 1,15 * 5 fires on the 1st and 15th plus every Friday, not only on Fridays that are the 1st.

When you need AND, leave one day field as an asterisk, or do the date test inside the command itself.

Two restricted day fields is one OR. Everyone meets this rule the hard way.

TRY IT THIS WEEK

Test it safely this week: put 30 4 1,15 * 5 echo in a scratch crontab and check a calendar for which Fridays double up.

Per cron(8): the -P option tells crond not to set PATH, PATH is instead inherited from the environment of the daemon, so by default crond sets a PATH of its own for the jobs it runs; per crontab(5), environment settings of the form name = value are allowed in the crontab and apply to the jobs that follow them.

build and run · No. 03
Runs as

A sparse PATH

Why terminal works

the daemon sets the PATH the job searchesyour terminalbinbinbinbinbinbinbinthe job's PATHbinbinbinfewer directories searchedso commands go unfoundthe fix, both halves:absolute paths inevery command, or setPATH at the top ofthe crontab, oncecommand not found under cron is a PATH question

The classic break: your terminal carries your login PATH, the job does not. crond sets a PATH of its own, inherited from the daemon only when crond runs with -P.

The manual's answer is boring and total: write absolute paths, /usr/local/bin/backup rather than backup, or set PATH once at the top of the crontab.

A command that is not found under cron is a PATH question nine times out of ten.

TRY IT THIS WEEK

Take one failing job this week and give its command the full absolute path. Then add a PATH line at the top of the crontab and retire the whole class of failure.

Part 3 of 4
files cron also reads
3

System jobs

crontab -e is only one of three homes: the spool, /etc/crontab and /etc/cron.d with its username field and stricter file rules, and the run-parts directories it feeds.


In this part
  1. 01Where jobs live
  2. 02Jobs in /etc/cron.d

Per cron(8): crond searches /var/spool/cron for crontab files which are named after accounts in /etc/passwd; it also searches /etc/anacrontab and any files in the /etc/cron.d directory, which have a different format; /etc/crontab is the system crontab; per crontab(1), the spool files are not intended to be edited directly, crontab -e installs them.

build and run · No. 04
System jobs

Where jobs live

Three homes

three homes, one daemon, checked every minute/var/spool/cronper-user tables/etc/crontabthe system table/etc/cron.d/system drop-inscrondthe spool files are named afteraccounts in /etc/passwdinstall through crontab -e;never edit the spool by handchanges are noticed within the minute:modtime or inotify, no restartuser jobs through crontab, system jobs in files

Three homes, one daemon: /var/spool/cron holds per-user tables named after accounts, while /etc/crontab and /etc/cron.d hold system jobs.

The spool is not for hand editing: install through crontab -e, which handles the file, the permissions and the reload.

User jobs go through crontab, system jobs go in files. The daemon reads both every minute.

TRY IT THIS WEEK

List your own table this week with crontab -l, then list /etc/cron.d and count how many packages shipped jobs there.

Per crontab(5), Jobs in /etc/cron.d: the jobs in cron.d and /etc/crontab are system jobs, used usually for more than one user, thus additionally the username is needed; the example job in /etc/cron.d is MAILTO=root then * * * * * root touch /tmp/file; per the CAVEATS, the files must be regular files, not executable and not writable for anyone else but the owner, and each entry must end in a newline.

build and run · No. 05
System jobs

Jobs in /etc/cron.d

One extra field

the username column is the whole differencemin30hour4dom*mon*dow*userrootcommandtouch /tmp/fevery field of an ordinary crontab, plus the one that says who runs itdrop a file in; read within the minuteregular files only; no world writeMAILTO=root works here too, on its own linepackages own cron.d, root edits it, users never need to

A cron.d file is a crontab with one extra field: the username, sitting between the schedule and the command. The manual's example is five stars, root, touch /tmp/file.

The discipline is higher here: regular files only, no group or world write, and the final-newline law applies. Drop a file in and cron reads it within the minute.

Packages own /etc/cron.d, root edits it, users never need to.

TRY IT THIS WEEK

Read one shipped file in /etc/cron.d this week and find the username column. That one field is the whole difference.

Per crontab(5), the EXAMPLE CRON FILE: 5 0 * * * with the command $HOME/bin/daily.job redirected with >> to $HOME/tmp/out with 2>&1; per crontab(1), crontab -l displays the current crontab; per cron(8), any output is mailed to the owner or MAILTO, and job output can be sent to syslog with the crond -s option.

build and run · No. 06
Real work

One habit to keep

Log your own runs

the manual's own line ends in a redirect$5 0 * * * $HOME/bin/daily.job>>$HOME/tmp/out 2>&1two stream chips:stdoutstderrboth into the same file, appendedabsolute pathsescaped percentsa final newlinea log you readpair it with crontab -l kept somewhere safe, and the syslog traceone append per line, and cron finally reports to you

The manual's own example ends with the habit: the job, then a redirect into a log, both streams. One file, both streams, a schedule you already trust.

Then read it: a log nobody opens is mail nobody reads. Pair it with crontab -l kept somewhere safe and the syslog trace.

Absolute paths, escaped percents, a final newline, a log you read. That is the whole religion.

TRY IT THIS WEEK

Add output redirection to every line you own this week. One append per line, and cron finally reports to you.

Index

Index


A sparse PATH7
Five fields, one line5
Jobs in /etc/cron.d10
One habit to keep11
The OR rule6
Where jobs live9