Scheduling tasks with cron
Run things automatically on a schedule.
cron is the classic Linux scheduler — it runs commands automatically at times you specify, from "every minute" to "3am on the first of the month." It is how routine work gets done without a human: backups, log rotation, cleanup jobs, health checks. You describe the schedule and the command in a crontab (cron table), and cron runs it faithfully in the background.
The five-field schedule
A cron schedule is five fields — minute, hour, day-of-month, month, day-of-week — followed by the command. A * means "every" for that field. So 0 3 * * * means "at minute 0 of hour 3, every day" (3am daily), and */15 * * * * means "every 15 minutes." Reading the five fields left to right is the whole skill; a comment line at the top of your crontab reminding you of the order is a common, sensible habit.
# ┌ minute (0-59)# │ ┌ hour (0-23)# │ │ ┌ day of month (1-31)# │ │ │ ┌ month (1-12)# │ │ │ │ ┌ day of week (0-6, Sun=0)# │ │ │ │ │0 3 * * * /opt/app/backup.sh # 3:00 AM every day*/15 * * * * /usr/local/bin/health-check.sh # every 15 minutes0 0 1 * * /opt/app/monthly-report.sh # midnight on the 1st of each month
Editing your crontab
crontab -e opens your personal crontab in an editor; save and the schedule is live immediately. crontab -l lists your current jobs. Each user has their own crontab, and there are also system-wide schedules in /etc/crontab and /etc/cron.d/. For a beginner, crontab -e for your own jobs and crontab -l to check them is all you need to start automating tasks.
$ crontab -e # edit YOUR crontab (opens $EDITOR; save to apply)$ crontab -l # list your current scheduled jobs0 3 * * * /opt/app/backup.sh*/15 * * * * /usr/local/bin/health-check.sh$ crontab -r # remove all your cron jobs (careful — no undo)
The gotchas that bite everyone
Cron jobs fail in predictable ways, and knowing them up front saves hours. Cron runs with a minimal environment and a bare PATH, so a script that works in your shell may fail in cron because a command is not found or a variable is unset — always use full paths (/usr/bin/python3, not python3) and do not rely on your .bashrc. And cron output goes nowhere by default, so a failing job is silent; redirect output to a log file so you can see what happened.
# full paths + capture output, so failures are visible instead of silent0 3 * * * /usr/bin/python3 /opt/app/backup.py >> /var/log/backup.log 2>&1# └ full path └ full path └ append stdout+stderr to a log