How to Schedule Tasks on Linux with Cron (Run a Script Every Night)

Backups at 2 am, a cleanup every Sunday, a check every five minutes — anything you'd otherwise have to remember to do can be handed to cron, the scheduler that's been in Linux since the beginning. One line per job in a file called the crontab.
Quick reference
| Task | Command |
|---|---|
| Edit your jobs | crontab -e |
| List your jobs | crontab -l |
| Edit root's jobs | sudo crontab -e |
| See what's run | journalctl -u cron -n 30 |
| Test a schedule | crontab.guru |
1. The five fields
Every line is a schedule followed by a command:
┌─ minute (0–59)
│ ┌─ hour (0–23)
│ │ ┌─ day of month (1–31)
│ │ │ ┌─ month (1–12)
│ │ │ │ ┌─ day of week (0–6, Sunday = 0)
│ │ │ │ │
* * * * * command
- means "every". Examples:
| Schedule | Meaning |
|---|---|
| 0 2 * * * | 2:00 am every day |
| */5 * * * * | every 5 minutes |
| 30 7 * * 1-5 | 7:30 am Monday to Friday |
| 0 3 * * 0 | 3:00 am every Sunday |
| 0 0 1 * * | midnight on the 1st of each month |
| @reboot | once, when the server starts |
Paste any of these into crontab.guru and it explains it in words.
2. Add a job
crontab -e
The first time it asks which editor to use — pick nano. Add a line at the bottom:
0 2 * * * /home/john/backup.sh >> /home/john/backup.log 2>&1
Save and exit. Cron picks it up immediately — no restart needed.
The >> file 2>&1 part saves everything the script prints (and any errors) to a log file. Without it, output goes nowhere useful.
3. Check it ran
cat /home/john/backup.log
journalctl -u cron -n 30
The journal shows every job cron started and when.
4. Jobs that need root
sudo crontab -e
Root's crontab is separate from yours. Use it for system jobs like cleaning Docker or renewing certificates:
0 4 * * 0 docker system prune -af >> /var/log/docker-prune.log 2>&1
5. The three rules of cron
- Use full paths. Cron doesn't know where python or docker is. Write /usr/bin/python3, not python3. Find a path with which python3.
- Make scripts executable. chmod +x backup.sh.
- Capture output. Always add >> logfile 2>&1 so you can see what happened.
Easier alternative for simple cases
Drop a script into /etc/cron.daily/, /etc/cron.weekly/ or /etc/cron.hourly/ (as root, executable, no file extension) and it runs at that interval. No schedule syntax at all.
Troubleshooting
It works when I run it by hand but not from cron. Almost always rule 1: a command without a full path, or a script that relies on being in a certain folder (add cd /home/john && before it).
It runs at the wrong time. Cron uses the server's time zone. timedatectl to check; tutorial 9 to change it.
The log file is empty. The script printed nothing, which may be fine. Add echo "done $(date)" to the end of the script to prove it ran.
"No crontab for john". You haven't created one yet. crontab -e makes it.
Percent signs in the command. % has a special meaning in crontab. Escape as \% — this bites people using date +%Y.
Wrapping up
Five fields, one line, crontab -e. Full paths, executable scripts, output to a log file. Check crontab.guru when you're unsure of a schedule, and journalctl -u cron when you're unsure it ran.
