The five fields
A cron expression is five values separated by spaces. Each one limits when the job runs.
┌───────── minute (0 to 59)
│ ┌─────── hour (0 to 23)
│ │ ┌───── day of month (1 to 31)
│ │ │ ┌─── month (1 to 12, or JAN to DEC)
│ │ │ │ ┌─ day of week (0 to 7, 0 and 7 are Sunday, or SUN to SAT)
│ │ │ │ │
* * * * *
The job runs at every minute where all five fields match the clock.
The symbols
| Symbol | Meaning | Example |
|---|---|---|
* | Every value. | * * * * * runs every minute. |
, | A list. | 0 9,17 * * * runs at 09:00 and 17:00. |
- | A range. | 0 9 * * 1-5 runs at 09:00, Monday to Friday. |
/ | A step. | */15 * * * * runs every 15 minutes. |
Shortcuts also work: @hourly, @daily, @weekly, @monthly and @yearly.
Three things that catch people out
- Day of month and day of week are joined by "or".
0 0 13 * 5does not mean "Friday the 13th". It runs on every 13th and on every Friday. - Steps restart each hour or day.
*/40 * * * *runs at minute 0 and minute 40 of every hour, so the gaps are 40 and then 20 minutes. - The time zone is the server's. A job set for 09:00 on a server in UTC runs at 10:00 or 11:00 in much of Europe, and it shifts by an hour when the clocks change.
Knowing the job actually ran
A correct schedule only says when cron will start the job. It does not tell you the job finished. Scripts fail without a sound: a full disk, an expired password, a server that was rebooted and never started cron again.
The usual fix is a heartbeat. The job requests a URL when it finishes, and a monitor alerts you when that request does not arrive on time.
30 2 * * * /usr/local/bin/backup.sh && curl -fsS -m 10 https://pulsx.net/api/beat/your-token
PULSX heartbeat monitors do this for free.