Cron Jobs: Scheduling Tasks on Linux
Cron is the Linux job scheduler that runs commands at specified times, dates, or intervals — from nightly backups every day at 2 AM to a health-check script every five minutes.
What You’ll Learn
- Crontab syntax and the five time fields
- Common cron schedules with real-world examples
- Managing crontabs with crontab -e, -l, and -r
- Logging cron output and debugging failed jobs
- Systemd timers — the modern alternative to cron
Why Cron Matters
Cron is the simplest way to automate recurring tasks on Linux. Certificate renewal, log rotation, database backups, system updates, monitoring checks — all of these should run automatically, not manually. Cron has been doing this reliably since the 1970s.
DodaZIP uses cron jobs to schedule nightly compression of log archives and weekly database backups.
Learning Path
flowchart LR
A[Linux Basics] --> B[Bash Scripting]
B --> C[Cron Jobs<br/>You are here]
C --> D[Systemd Timers]
D --> E[Monitoring & Alerting]
style C fill:#f90,color:#fff
Crontab Syntax
A crontab entry has five time fields followed by the command:
* * * * * command_to_run
│ │ │ │ │
│ │ │ │ └── Day of week (0-7, 0=Sunday)
│ │ │ └──── Month (1-12)
│ │ └────── Day of month (1-31)
│ └──────── Hour (0-23)
└────────── Minute (0-59)Special Characters
| Character | Meaning | Example |
|---|---|---|
* | Every | * * * * * = every minute |
*/n | Every n | */5 * * * * = every 5 minutes |
, | List | 0 9,17 * * 1-5 = weekdays at 9 AM and 5 PM |
- | Range | 0 9-17 * * * = every hour from 9 AM to 5 PM |
Common Schedules
# ┌─ Minute ──┐ ┌─ Hour ──┐ ┌─ Day ──┐ ┌─ Month ──┐ ┌─ Day of Week ──┐
# Every minute
* * * * * /path/to/script.sh
# Every 5 minutes
*/5 * * * * /path/to/script.sh
# Every hour at minute 0
0 * * * * /path/to/script.sh
# Daily at 2:30 AM
30 2 * * * /path/to/script.sh
# Every Monday at 3 AM
0 3 * * 1 /path/to/script.sh
# First day of every month at 1 AM
0 1 1 * * /path/to/script.sh
# Every weekday at 9 AM and 5 PM
0 9,17 * * 1-5 /path/to/script.sh
# Every 15 minutes during business hours
*/15 9-17 * * 1-5 /path/to/script.sh
# Twice a year (June 1 and December 1 at midnight)
0 0 1 6,12 * /path/to/script.shManaging Crontabs
# Edit crontab for current user
crontab -e
# List current crontab entries
crontab -l
# Remove entire crontab
crontab -r
# Edit another user's crontab (root only)
sudo crontab -u alice -e
# Restore crontab from file
crontab backup.txtComplete Example
# /tmp/backup.sh
#!/bin/bash
BACKUP_DIR="/var/backups/database"
TIMESTAMP=$(date +%Y-%m-%d_%H%M)
FILENAME="db_backup_$TIMESTAMP.sql"
mkdir -p "$BACKUP_DIR"
pg_dump myapp > "$BACKUP_DIR/$FILENAME"
gzip "$BACKUP_DIR/$FILENAME"
# Remove backups older than 30 days
find "$BACKUP_DIR" -name "*.sql.gz" -mtime +30 -delete
echo "Backup completed: $FILENAME.gz"# crontab entry: run daily at 2 AM
0 2 * * * /tmp/backup.sh >> /var/log/backup.log 2>&1Logging and Output
By default, cron mails output to the user. For practical use, redirect output to a log file:
# Redirect stdout and stderr to a log file
30 2 * * * /path/to/script.sh >> /var/log/myscript.log 2>&1
# Discard output (run silently)
30 2 * * * /path/to/script.sh > /dev/null 2>&1
# Log with timestamp
30 2 * * * echo "[$(date)] Starting backup" >> /var/log/backup.log && \
/path/to/backup.sh >> /var/log/backup.log 2>&1Check cron logs:
# View cron execution log (Debian/Ubuntu)
sudo grep CRON /var/log/syslog
# View cron execution log (RHEL/CentOS)
sudo grep CRON /var/log/cronExpected log output:
Jun 19 02:00:01 server CRON[12345]: (alice) CMD (/tmp/backup.sh >> /var/log/backup.log 2>&1)Environment Variables in Cron
Cron runs with a minimal environment — PATH is often just /usr/bin:/bin. Always use full paths or set PATH in your crontab:
# Set environment variables at the top of crontab
PATH=/usr/local/bin:/usr/bin:/bin
SHELL=/bin/bash
HOME=/home/alice
MAILTO=alice@example.com
# Now you can use commands without full paths
30 2 * * * backup.shSystemd Timers (Modern Alternative)
Cron works, but systemd timers offer better logging, dependency management, and integration with systemd services:
# /etc/systemd/system/backup.service
[Unit]
Description=Database backup service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
User=postgres# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup daily at 2 AM
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.targetsudo systemctl daemon-reload
sudo systemctl enable backup.timer
sudo systemctl start backup.timerWhen to use systemd timers vs cron
- Cron: Simpler, works everywhere, great for quick jobs
- Systemd timers: Better logging (
journalctl), dependency management, can handle missed runs withPersistent=true
Common Errors
1. Script Works Manually but Not in Cron
Cron runs with a limited PATH. Always use absolute paths or set PATH in crontab. Scripts that rely on environment variables (like $HOME) need explicit definition.
2. Missing Execute Permission
Cron can’t run scripts without execute permission: chmod +x script.sh.
3. No Output Redirect
Without >> logfile 2>&1, cron output is mailed but often lost. Always redirect to a log file.
4. Percent Sign Not Escaped
The % character in crontab must be escaped with backslash. Use $(date +\%Y-\%m-\%d) instead.
5. Time Zone Confusion
Cron uses the system time zone. Check timedatectl if your jobs run at unexpected times.
6. Overlapping Jobs
If a job takes longer than its interval (e.g., backup takes 10 minutes, runs every 5 minutes), jobs overlap. Use flock to prevent:
*/5 * * * * /usr/bin/flock -n /tmp/myscript.lock /path/to/script.shPractice Questions
What does
*/15 * * * *mean? Run every 15 minutes.How do you set environment variables in a crontab? Add them at the top of the crontab file, before job entries:
PATH=/usr/bin:/bin.Why might a script work manually but fail in cron? Cron has a minimal PATH and doesn’t load profile files. Use full paths or set PATH in crontab.
How do you view cron execution logs? Check
/var/log/syslog(Debian) or/var/log/cron(RHEL) withgrep CRON.What is an advantage of systemd timers over cron? Better logging with journalctl, dependency management via systemd units, and
Persistent=truefor missed runs.
Challenge: Set up a cron job that: (1) runs a backup script daily at 2 AM, (2) logs output with timestamps, (3) removes backups older than 7 days, (4) sends an email alert if the backup fails. Then migrate it to a systemd timer.
FAQ
What’s Next
| Tutorial | What You’ll Learn |
|---|---|
| Systemd Service Management | Modern service and timer management |
| Linux Administration Basics | Foundational server administration |
| Bash Scripting Guide | Writing scripts that cron can run |
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro. Updated 2026-06-19.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro