Cron Jobs Explained: The Complete Beginner's Tutorial
9 min read · Updated 2026-08-07
Every server you've ever touched probably has cron jobs running right now — log rotations, backups, health checks. The syntax is five fields and 40 years old, and once it clicks, it clicks forever.
The five fields
A cron expression is: minute hour day-of-month month day-of-week command
┌───────────── minute (0 - 59) │ ┌───────────── hour (0 - 23) │ │ ┌───────────── day of month (1 - 31) │ │ │ ┌───────────── month (1 - 12) │ │ │ │ ┌───────────── day of week (0 - 6, Sun=0) │ │ │ │ │ * * * * *
* means "every value"; */5 means "every 5 units"; 1,15 means "the 1st and 15th"; 9-17 means "9am through 5pm".
The recipes everyone actually uses
0 * * * *— top of every hour (hourly cleanup jobs)0 0 * * *— midnight daily (nightly backups)0 9 * * 1-5— 9am on weekdays (standup reminders)*/15 * * * *— every 15 minutes (health checks)0 0 1 * *— first of the month (monthly reports)30 2 * * 0— 2:30am Sundays (weekend maintenance)
Don't memorize — build them visually with the cron expression builder and copy the result.
The gotchas that bite everyone
1. Day-of-month AND day-of-week is an OR. 0 0 13 * 5 runs on the 13th and every Friday — not "Friday the 13th". 2. Timezone: cron uses the server's local time unless CRON_TZ is set — a daylight-saving shift can fire a job twice or never. 3. Minimal environment: cron runs with a tiny PATH, so always use absolute paths for binaries (/usr/bin/python3, not python3). 4. The % character needs escaping as \% in crontab lines.
Testing before you deploy
Never learn about a bad schedule from a 3am page. Validate the expression and preview the next five fire times in the builder, then confirm on staging: temporarily set the job to * * * * * (every minute), watch the logs for two minutes, then switch to the real schedule.
Modern alternatives
systemd timers (better logging), Kubernetes CronJobs (cluster-aware), and GitHub Actions schedules all use the same five-field syntax — learning cron once pays off across every platform.
Frequently Asked Questions
What does */5 mean in cron?
Every 5 units of that field. In the minute field, */5 = at :00, :05, :10 … :55 every hour.
How do I run a cron job on the last day of the month?
Cron can't express it directly. The standard trick: run daily and exit unless tomorrow's date is the 1st — [ $(date -d tomorrow +%d) -eq 1 ] || exit 0.
Why isn't my cron job running?
Check three things: absolute paths for all commands, the daemon is running (systemctl status cron), and stderr isn't being discarded — redirect to a log: * * * * * /path/cmd >> /var/log/myjob.log 2>&1.
How do I see my scheduled crons?
crontab -l lists your user crontab; system-wide ones live in /etc/crontab and /etc/cron.d/.