Cron & Scheduling
Reference: Debian Wiki — cron · Ubuntu Docs — CronHowto · man 5 crontab
Cron Syntax
┌───────── minute (0–59)
│ ┌─────── hour (0–23)
│ │ ┌───── day of month (1–31)
│ │ │ ┌─── month (1–12 or jan–dec)
│ │ │ │ ┌─ day of week (0–7, 0 and 7 = Sunday, or sun–sat)
│ │ │ │ │
* * * * * command
Common Examples
# Every minute
* * * * * /usr/local/bin/script.sh
# Every day at 2am
0 2 * * * /usr/local/bin/backup.sh
# Every Monday at 6am
0 6 * * 1 /usr/local/bin/weekly.sh
# Every 15 minutes
*/15 * * * * /usr/local/bin/check.sh
# First day of every month at midnight
0 0 1 * * /usr/local/bin/monthly.sh
# Weekdays at 8am
0 8 * * 1-5 /usr/local/bin/workday.sh
# Every 6 hours
0 */6 * * * /usr/local/bin/sync.sh
# Multiple specific hours (9am, 1pm, 5pm)
0 9,13,17 * * * /usr/local/bin/reminder.sh
Tip
Use crontab.guru to test and validate cron expressions.
crontab — User Cron Jobs
Each user has their own crontab. User crontabs run as that user.
# Edit your crontab
crontab -e
# View your crontab
crontab -l
# Remove your crontab entirely
crontab -r
# Edit another user's crontab (root only)
sudo crontab -u username -e
Example User Crontab
# Set shell and PATH explicitly (cron has a minimal environment)
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# Redirect output to log file (suppress email)
0 2 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
# Discard all output entirely
*/5 * * * * /usr/local/bin/check.sh > /dev/null 2>&1
# Send output to syslog via logger
0 3 * * * /usr/local/bin/cleanup.sh 2>&1 | logger -t cleanup
Cron environment is minimal
Cron doesn't load your .bashrc or .profile. Always use full paths for commands and scripts, and set PATH at the top of your crontab if needed.
System Cron (/etc/cron*)
System-level cron jobs that run as root live in several directories:
/etc/cron.d/ # Individual crontab-style files (specify user)
/etc/cron.hourly/ # Scripts dropped here run hourly
/etc/cron.daily/ # Scripts dropped here run daily
/etc/cron.weekly/ # Scripts dropped here run weekly
/etc/cron.monthly/ # Scripts dropped here run monthly
/etc/crontab # System crontab (includes username field)
/etc/cron.d/ Format
Files in cron.d require a username field (unlike user crontabs):
# /etc/cron.d/myapp
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# minute hour dom month dow user command
0 2 * * * root /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
Drop-in Scripts (cron.daily, cron.weekly, etc.)
# Copy script to the appropriate directory
sudo cp myscript.sh /etc/cron.daily/myscript
# Must be executable and owned by root
sudo chmod 755 /etc/cron.daily/myscript
sudo chown root:root /etc/cron.daily/myscript
# Scripts must NOT have a file extension (cron ignores files with dots)
# Good: /etc/cron.daily/backup
# Bad: /etc/cron.daily/backup.sh ← will NOT run
anacron
anacron runs jobs that were missed because the machine was off — unlike cron, it doesn't require the system to be running at the exact scheduled time.
# Config file
cat /etc/anacrontab
# Example entry
# period delay job-id command
1 5 daily.job /etc/cron.daily
7 10 weekly.job /etc/cron.weekly
/etc/cron.daily, weekly, and monthly are typically run through anacron rather than cron directly.
Debian vs Ubuntu
Both include anacron by default on desktop installs. On minimal server installs, anacron may not be present — verify with which anacron. The daily/weekly/monthly directories still work but through the system crontab instead.
Viewing Cron Logs
# Debian — cron logs to syslog
grep CRON /var/log/syslog
grep CRON /var/log/syslog | tail -20
# Ubuntu (systemd journal)
journalctl -u cron
journalctl -u cron -f # follow live
journalctl -u cron --since "1 hour ago"
# Check if cron is running
systemctl status cron
Systemd Timers as Cron Alternative
For new services, systemd timers are more robust than cron — they log to the journal, handle missed runs, and integrate with service dependencies. See the Systemd page for full details.
Quick comparison:
| Feature | cron | systemd timer |
|---|---|---|
| Easy syntax | ✅ | ❌ (two files) |
| Logs to journal | ❌ | ✅ |
| Run if missed | Only with anacron | ✅ (Persistent=true) |
| Dependency handling | ❌ | ✅ |
| Per-user | ✅ | ✅ |
| No extra install | ✅ | ✅ |