What is a cron job? The five fields and where cron actually runs
A cron job is a command scheduled to run automatically at fixed times, defined by a short expression that most Unix-like systems have understood for decades. If you have ever seen a line like 0 3 * * * /usr/local/bin/backup.sh, that is cron telling a machine to run a backup at 3am every day. The syntax is compact, which makes it powerful and easy to get subtly wrong.
The five fields
A standard cron expression has five fields separated by spaces, read left to right:
* * * * *
│ │ │ │ │
│ │ │ │ └─ day of week (0-7, Sun = 0 or 7)
│ │ │ └──── month (1-12)
│ │ └─────── day of month (1-31)
│ └────────── hour (0-23)
└───────────── minute (0-59)
Each field accepts a few operators: * for every value, a number for an exact value, a-b for a range, a,b,c for a list, and */n for a step. So 0 3 * * * reads as minute 0, hour 3, every day of month, every month, every day of week, which is 3am daily.
| Expression | Meaning |
|---|---|
* * * * * | every minute |
0 * * * * | top of every hour |
30 2 * * * | 2:30am every day |
0 9 * * 1 | 9am every Monday |
0 0 1 * * | midnight on the first of each month |
One real trap: when both day-of-month and day-of-week are restricted, most cron implementations treat them as OR, not AND. 0 0 13 * 5 fires on the 13th of the month and on every Friday, not only on Friday the 13th. If only one of the two day fields is a *, this ambiguity does not arise.
Where cron runs
"Cron" names a family of schedulers, not one program. The job lives in different places depending on your environment:
- crontab. The classic Unix cron daemon reads per-user tables edited with
crontab -eand system tables in/etc/crontaband/etc/cron.d/. This is what people usually mean by cron on a Linux server. - systemd timers. Modern Linux distributions often prefer timer units over crontab. They use a different syntax but cover the same ground, with better logging, dependency handling, and the ability to run missed jobs on boot.
- Cloud schedulers. Managed platforms expose cron-style scheduling without a server you maintain: cloud function triggers, container platform cron jobs, and hosted schedulers. They almost always accept the same five-field expression, so the syntax you learn transfers.
The expression is portable; the surrounding machinery is not. A string that works in crontab generally works in a cloud scheduler, but the way you install it, the time zone it assumes, and how failures are reported all differ.
What happens when the machine is off
This is the question that bites people. Classic cron has no memory. If the machine is powered off or asleep at the scheduled time, that run is simply skipped, and cron does not catch up when the machine returns. A nightly 3am backup on a laptop that was closed at 3am never runs, with no error and no retry.
Three things follow from this:
- Use
anacronor a catch-up mechanism for jobs on machines that are not always on.anacrontracks when a job last ran and executes overdue jobs after boot, which is why laptops use it for daily and weekly maintenance. - systemd timers can backfill with
Persistent=true, running a missed timer once the system is back up. - Cloud schedulers run on always-on infrastructure, so the off-machine problem disappears, but they introduce their own: a job can fire twice if the platform retries, so make the work idempotent.
Time zone is the other quiet hazard. Traditional cron runs in the system's local time, which means daylight saving transitions can skip or double a job scheduled during the shifted hour. Many cloud schedulers default to UTC to avoid this. Always confirm which zone your scheduler assumes.
Writing the expression
The fields are simple, but a wrong digit means a job that runs at the wrong time and nobody notices for weeks. To build an expression, read it back in plain English, and preview the next few run times before you trust it, use the Cron Generator.