Crontab Format & Syntax Explained (with Examples)

Updated Jun 2026 · originally published Dec 2009 · Tested on Ubuntu 24.04, Debian 12, RHEL 9, macOS 14

Advertisement

A crontab is a configuration file that tells the cron daemon which commands to run and when. Each line holds five time fields (minute, hour, day of month, month, day of week) followed by the command to run. cron is the standard task scheduler on Unix-like systems — Linux, the BSDs, Solaris, and macOS — running commands automatically in the background at fixed intervals.

This page is the complete crontab reference: the format and syntax field by field, the most-copied examples, special strings like @daily, the environment gotchas that cause most failures, and how to debug a job that won’t run.

What cron actually is

cron is a daemon started at boot from your init system. The name comes from chronos, the Greek word for time. You can stop, start, or restart it through your service manager — systemctl restart cron on Debian/Ubuntu, or systemctl restart crond on RHEL/Fedora.

A crontab (cron table) is the file that holds your scheduled entries. You never edit it directly — you use the crontab command, which validates your changes before installing them.

Crontab restrictions

Whether you can use cron at all is controlled by two files:

  • If /etc/cron.allow exists, your username must be listed in it.
  • If only /etc/cron.deny exists, you can use cron unless you’re listed in it.
  • If neither file exists, on most systems only root may use cron.

The allow/deny files contain one username per line. (Older systems keep these under /usr/lib/cron/.)

Crontab commands

Set your preferred editor first, then use the four core commands:

export EDITOR=vi    # or nano, emacs, etc.
CommandWhat it does
crontab -eEdit your crontab (creates one if it doesn’t exist)
crontab -lList the contents of your crontab
crontab -rRemove your crontab entirely
crontab -vShow when you last edited it (limited support)

To work with another user’s crontab, add -u: sudo crontab -u www-data -l.

How to read a crontab entry

Read the five fields left to right: minute, hour, day-of-month, month, day-of-week, then the command. So 30 2 * * 1 /backup.sh reads as “at 2:30 AM every Monday, run /backup.sh.”

Crontab format and syntax

The crontab format is five time fields plus a command. This is the layout every crontab entry follows:

* * * * * command
│ │ │ │ │
│ │ │ │ └─ day of week (0–6, Sunday = 0 or 7)
│ │ │ └─── month (1–12)
│ │ └───── day of month (1–31)
│ └─────── hour (0–23)
└───────── minute (0–59)

Crontab fields and columns explained

Each of the five columns controls one part of the schedule, read left to right:

FieldColumnAllowed values
1Minute0–59
2Hour0–23
3Day of month1–31
4Month1–12 (or Jan–Dec)
5Day of week0–6 (Sun=0, or 7; or Sun–Sat)

A * means “every valid value for this field.” Beyond *, each field accepts:

  • Lists1,15,30 (these specific values)
  • Ranges9-17 (an inclusive range)
  • Steps*/15 (every 15th value)

Step values (the */5 syntax)

Step syntax runs a job at regular intervals. */5 in the minute field means “every 5 minutes”; */2 in the hour field means “every 2 hours.” You can combine a step with a range too: 0-30/10 means every 10 units from 0 to 30.

*/5 * * * * /path/to/script.sh     # every 5 minutes
0 */2 * * * /path/to/script.sh     # every 2 hours, on the hour

Crontab examples (most-copied)

These are the crontab expressions people copy most often:

ExpressionRuns
* * * * *Every minute
0 * * * *Top of every hour
30 2 * * *Daily at 2:30 AM
0 9 * * 1-5Weekdays at 9:00 AM
0 0 1 * *First of every month, midnight
*/15 * * * *Every 15 minutes

A worked example — remove temp files every day at 6:30 PM:

30 18 * * * rm /home/someuser/tmp/*

Every hour

Keep the hour field as *. Set the minute to 0 to fire at the top of the hour, or any minute to offset it:

0 * * * * /path/to/script.sh     # top of every hour
15 * * * * /path/to/script.sh    # 15 past every hour

Every minute

* * * * * /path/to/script.sh

Specific months or weekdays

# 00:30 on the 1st of January, June, and December
30 0 1 1,6,12 * /path/to/script.sh

# 8:00 PM every weekday in October
0 20 * 10 1-5 /path/to/script.sh

# Midnight on the 1st, 10th, and 15th of every month
0 0 1,10,15 * * /path/to/script.sh

For 75+ ready-to-use recipes grouped by task — backups, monitoring, log rotation, business-hours patterns — see the crontab examples cookbook.

Special strings: @daily, @reboot, and shortcuts

Most cron implementations accept named shortcuts in place of the five fields. They are easier to read than the numeric form and cover the common schedules:

StringEquivalentRuns
@rebootOnce, at startup
@yearly or @annually0 0 1 1 *Once a year, midnight Jan 1
@monthly0 0 1 * *First of the month, midnight
@weekly0 0 * * 0Sunday, midnight
@daily or @midnight0 0 * * *Every day, midnight
@hourly0 * * * *Top of every hour
@daily /home/user/scripts/cleanup.sh
@reboot /home/user/scripts/start-tunnel.sh

@reboot is the one worth remembering: it runs a job once each time the machine boots, which is handy for starting a process that has no service unit.

Crontab environment

This is the single most common reason a job “works in my shell but not in cron.” cron runs your command from your home directory under a minimal environment:

HOME=/home/your-user
LOGNAME=your-user
PATH=/usr/bin:/bin
SHELL=/bin/sh

Note what’s missing: cron does not source your .bashrc, .profile, or any shell startup file. No aliases, no functions, no custom PATH. Two consequences:

  1. Use absolute paths for every command. Find them with which docker, which node, etc. Tools in /usr/local/bin or ~/.local/bin won’t be found otherwise.
  2. If you need your shell environment, source it explicitly inside the script cron calls, or set PATH= and SHELL=/bin/bash at the top of the crontab.
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

0 2 * * * /home/user/scripts/backup.sh

Disable email

By default cron emails the job’s output to the local user. To silence it, set MAILTO to an empty string at the top of the crontab:

MAILTO=""

Set it to an address instead to route output somewhere you’ll actually see it.

Generate a log file

Redirect both stdout and stderr to a file so failures aren’t silent:

*/5 * * * * /path/to/script.sh >> /var/log/myjob.log 2>&1

The >> appends; use > to overwrite each run. The 2>&1 sends stderr to the same place as stdout — and the order matters. >> file 2>&1 captures both; 2>&1 >> file does not. (For the full explanation, see what 2>&1 means in shell.)

Crontab file location

User crontabs are stored — but don’t edit these directly, always use crontab -e:

  • Debian / Ubuntu: /var/spool/cron/crontabs/
  • RHEL / CentOS / Fedora: /var/spool/cron/
  • System-wide: /etc/crontab and the /etc/cron.d/ directory

Note that /etc/crontab and files in /etc/cron.d/ use a different syntax — they add a username field between the time fields and the command:

# /etc/crontab — note the extra "root" field
30 2 * * * root /path/to/script.sh

Why isn’t my cron job running?

Work through these in order — the first three catch most failures:

  1. Did cron fire it? Check the log: journalctl -u cron --since "1 hour ago" (or -u crond on RHEL). No entry means the schedule is wrong or the crontab isn’t installed for that user.
  2. Did the command succeed? Redirect output to a file (see above) and read it.
  3. Is it the PATH problem? See Crontab environment — this is the usual culprit.
  4. Is the script executable? chmod +x script.sh, and confirm the shebang line. Windows line endings (\r\n) break the shebang — fix with dos2unix.
  5. Right user? crontab -e edits the current user’s crontab. Root’s is separate: sudo crontab -l.
  6. The day-of-month / day-of-week trap? See the warning above.

For the full systematic walkthrough — SELinux, time zones, overlap prevention, and a copy-paste debug crontab — see the complete cron debugging checklist.

When not to use cron

cron is the right tool for simple, time-based jobs. If you need more, modern alternatives are worth knowing:

  • systemd timers — dependency management, persistent jobs across reboots, randomized delays, and journaled output. Native on most current Linux distros.
  • Kubernetes CronJobs — the same cron syntax, for containerized workloads, with concurrency policies and history limits.
  • Cloud schedulers — AWS EventBridge Scheduler, GCP Cloud Scheduler, Azure Logic Apps — for serverless workloads.

Rule of thumb: if your job needs retries, monitoring, or dependencies on other jobs, you’ve outgrown cron.

Keep going with these hands-on references:

Crontab reference books

Want a deeper, offline reference? Browse our shelf of Linux and DevOps books — the shell scripting and system administration titles cover cron, systemd, and automation in depth.

Advertisement