What is a cron job?
cron is the time-based job scheduler built into every Unix-like system. The cron daemon (crond) wakes up every minute, reads a set of crontab ("cron table") files, and runs any command whose schedule matches the current minute.
A cron job is just one line: a five-field schedule, followed by the command to run.
The crontab line format
# ┌───────── minute (0 - 59) # │ ┌─────── hour (0 - 23) # │ │ ┌───── day of month (1 - 31) # │ │ │ ┌─── month (1 - 12, or JAN-DEC) # │ │ │ │ ┌─ day of week (0 - 6, 0 = Sunday, or SUN-SAT) # │ │ │ │ │ * * * * * /path/to/command --flag
Each field accepts: * (any), lists 1,15,30, ranges 9-17, and steps */15. So 0 9 * * 1-5 means "at 09:00, Monday through Friday".
Not sure what a line means? Paste it into the crontab.in editor and read it in plain English.
Special strings
Instead of five fields you can use a shortcut:
@yearly (or @annually) 0 0 1 1 * @monthly 0 0 1 * * @weekly 0 0 * * 0 @daily (or @midnight) 0 0 * * * @hourly 0 * * * * @reboot run once when cron starts
How to edit your crontab
crontab -e # edit YOUR user crontab crontab -l # list it crontab -r # remove it (careful!) sudo crontab -e -u www-data # edit another user's crontab
System-wide jobs live in /etc/crontab and /etc/cron.d/* — these have an extra field for the user to run as:
# m h dom mon dow user command 0 3 * * * root /opt/backup.sh
The gotchas that bite everyone
- Minimal PATH. cron runs with a bare environment —
PATHis usually just/usr/bin:/bin. Use absolute paths (/usr/local/bin/python3) or setPATH=at the top of the crontab. - The
%character is special. In a crontab,%means newline. Escape it as\%(common indate +\%Y-\%m-\%d). - MAILTO. If a job prints output, cron tries to email it to the local user. Set
MAILTO=you@example.com, or redirect output (>> /var/log/job.log 2>&1) to avoid surprise mail. - Timezone. Classic cron runs in the system timezone, and it does not adjust for DST cleanly — a 02:30 job may run twice or not at all on transition days. Check yours with
timedatectl. - Silent failure. cron will happily not-run a broken job forever and tell no one. (That is the whole reason monitoring exists — see below.)
Monitor it free with cron.watch
Cron itself has no idea whether your command succeeded. A schedule is only a promise — cron.watch tells you if the job actually ran, alerts you when it silently fails, skips, or runs long, and keeps a history of every run.
# tack a check-in onto any cron line 0 3 * * * /opt/backup.sh && curl -fsS https://cron.watch/s/your-id # or capture the exit code either way 0 3 * * * /opt/backup.sh; curl -fsS https://cron.watch/s/your-id/$?