Cron + scheduling cheatsheet.
crontab
crontab -e # edit your cron
crontab -l # list
crontab -r # remove all
crontab -u alice -e # edit alice's (root only)
sudo crontab -e # root's
Syntax
m h dom mon dow command
* * * * * /opt/script.sh
# minute (0-59)
# hour (0-23)
# day of month (1-31)
# month (1-12)
# day of week (0-7, 0/7 = sunday)
Examples:
0 2 * * * daily 02:00
*/15 * * * * every 15 min
0 */2 * * * every 2 hours
0 0 * * 0 weekly Sunday midnight
0 0 1 * * monthly 1st
0 9-17 * * 1-5 hourly 9-5 weekdays
@reboot on boot
@daily daily midnight
@hourly
Environment
Cron has minimal environment. Set explicitly:
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
[email protected]
0 2 * * * /opt/script.sh
/etc/crontab
System cron with user field:
m h dom mon dow user command
0 2 * * * root /opt/backup.sh
/etc/cron.d/, hourly/, daily/, etc
Drop-in directories. /etc/cron.daily/ runs via run-parts.
anacron
For systems not always on. Catches up missed runs.
/etc/anacrontab:
1 5 cron.daily run-parts /etc/cron.daily
7 25 cron.weekly run-parts /etc/cron.weekly
period / delay / job-id / command.
Logging
Cron logs to syslog/journal:
journalctl -u cron
journalctl -u crond # RHEL
Redirect script output:
0 2 * * * /opt/backup.sh > /var/log/backup.log 2>&1
Capture failures
0 2 * * * /opt/backup.sh || curl -fsS https://hc-ping.com/UUID/fail
Better: healthchecks.io / cronitor:
0 2 * * * curl -fsS https://hc-ping.com/UUID/start && /opt/backup.sh && curl -fsS https://hc-ping.com/UUID
systemd timer (alternative)
# backup.timer
[Unit]
Description=Daily backup
[Timer]
OnCalendar=daily
Persistent=true
RandomizedDelaySec=600
[Install]
WantedBy=timers.target
# backup.service
[Unit]
Description=Backup
[Service]
Type=oneshot
ExecStart=/opt/backup.sh
systemctl enable --now backup.timer
systemctl list-timers
Advantages over cron:
- Integration with journal.
- Service-style env / sandboxing.
- Random delay.
- Dependencies.
Persistent=truecatches up missed.
at (one-time)
at 14:00 << EOF
echo "task" | mail alice
EOF
atq # list pending
atrm 1
Locking (prevent overlap)
0 2 * * * flock -n /tmp/backup.lock /opt/backup.sh
Or in systemd: services serialize automatically.
Idempotency
Cron may overlap if jobs run long. Either:
- Use flock.
- Make script check + skip if already running.
- systemd unit with
RemainAfterExit=yesfor one-shot semantics.
Common mistakes
- Cron
PATHdiffers from shell → “command not found”. - Forgetting absolute paths in scripts.
- Long-running job overlaps itself.
- Logs lost — redirect or
MAILTO. - DST changes cause double/missed runs.
MAILTOnot set → output silently dropped (no MTA).
Read this next
If you want my healthchecked cron setup, it’s at rajpoot.dev .
Building something AI-, backend-, or data-heavy and want a second pair of eyes? I do consulting and freelance work — see my projects and ways to reach me at rajpoot.dev .