Cron and Scheduled Tasks
cron is the classic Linux task scheduler. It runs commands on a schedule — every minute, every hour, every day, or any combination you define. Understanding the syntax and the gotchas makes it reliable.
Series: Learning Linux from Scratch
- 1. Learning Linux from Scratch — After a Full IT Apprenticeship
- 2. What is Linux?
- 3. The Filesystem
- 4. Users and Permissions
- 5. Installing and Managing Software
- 6. Text Editors
- 7. Shell Scripting Basics
- 8. Process Management
- 9. Networking Fundamentals
- 10. SSH
- 11. systemd and Services
- 12. Disk Management
- 13. Users and Groups — In Depth
- 14. Cron and Scheduled Tasks
- 15. Firewall — iptables and ufw
- 16. Environment Variables and the Shell
- 17. Log Management
- 18. Kernel Module Management
- 19. The /proc Filesystem — In Depth
- 20. The /sys Filesystem and udev
- 21. Kernel Parameters and sysctl
- 22. Compiling and Installing a Custom Kernel
cron is the classic Linux task scheduler. It runs commands on a schedule — every minute, every hour, every day, every week, or any combination you define. It has been part of Unix systems for decades and it is still the most widely used tool for scheduled jobs.
How cron works
The cron daemon runs in the background and checks every minute whether any scheduled job should run. Jobs are defined in crontab files — one per user, plus system-wide files.
crontab syntax
Each cron job is one line with six fields:
* * * * * command
│ │ │ │ │
│ │ │ │ └─ day of week (0-7, 0 and 7 are Sunday)
│ │ │ └─── month (1-12)
│ │ └───── day of month (1-31)
│ └─────── hour (0-23)
└───────── minute (0-59)
A * means every value for that field.
Examples:
# run every minute
* * * * * /home/jan/scripts/check.sh
# run at 2:30am every day
30 2 * * * /home/jan/scripts/backup.sh
# run at midnight on the 1st of every month
0 0 1 * * /home/jan/scripts/monthly.sh
# run every 15 minutes
*/15 * * * * /home/jan/scripts/monitor.sh
# run at 9am on weekdays only
0 9 * * 1-5 /home/jan/scripts/report.sh
# run at 6am and 6pm
0 6,18 * * * /home/jan/scripts/twice-daily.sh
The */n syntax means every n units. */15 in the minute field means every 15 minutes.
Editing your crontab
crontab -eThis opens your user crontab in your default editor. Each user has their own crontab, and jobs run as that user.
To list your current jobs:
crontab -lTo remove your entire crontab:
crontab -rBe careful with -r. It deletes everything with no confirmation.
System crontabs
Beyond user crontabs, there are system-wide locations:
/etc/crontab— the main system crontab. Has an extra field for the username to run as./etc/cron.d/— drop individual crontab files here. Same format as/etc/crontab./etc/cron.hourly/,/etc/cron.daily/,/etc/cron.weekly/,/etc/cron.monthly/— drop scripts directly into these directories and they run at the corresponding interval.
The /etc/crontab format has an extra username field:
# minute hour dom month dow user command
0 2 * * * root /usr/local/bin/backup.sh
Cron environment
Cron jobs run in a minimal environment — much more minimal than your interactive shell. This causes a lot of confusion.
The PATH in a cron job is usually just /usr/bin:/bin. If your script uses a command that lives elsewhere, cron will not find it.
The safest approach is to use full paths in cron commands:
0 2 * * * /usr/bin/python3 /home/jan/scripts/backup.py
Or set PATH at the top of your crontab:
PATH=/usr/local/bin:/usr/bin:/bin:/home/jan/.local/bin
0 2 * * * backup.py
Capturing output
By default, cron emails output to the local user. On most systems this goes nowhere useful. Redirect output to a log file instead:
0 2 * * * /home/jan/scripts/backup.sh >> /var/log/backup.log 2>&1
>>appends stdout to the log file2>&1redirects stderr to stdout (so errors also go to the log)
To suppress all output completely:
0 2 * * * /home/jan/scripts/backup.sh > /dev/null 2>&1
anacron
cron assumes the system is always running. If the machine is off when a job should run, that job is skipped.
anacron handles this by tracking when jobs last ran and running missed jobs on the next boot or startup. It is designed for desktops and laptops that are not always on.
anacron is configured in /etc/anacrontab:
# period delay job-identifier command
1 5 daily.jobs run-parts /etc/cron.daily
7 10 weekly.jobs run-parts /etc/cron.weekly
period— how often to run (in days)delay— how many minutes to wait after startup before runningjob-identifier— used for tracking when the job last rancommand— what to run
anacron is not a replacement for cron. It covers scheduled maintenance tasks on systems that are not always on. cron handles precise time-based scheduling.
Debugging cron jobs
When a cron job does not run as expected:
- Check the system log for cron entries:
grep cron /var/log/syslog - Make the script executable:
chmod +x script.sh - Test the script manually as the cron user:
sudo -u jan /path/to/script.sh - Use full paths for all commands inside the script
- Log output to a file and check it after the job should have run
cron is straightforward but the environment differences between interactive shells and cron catch almost everyone at least once. Full paths and explicit output redirection solve most problems.
Next up: the firewall — how iptables works and how to manage it with ufw.