Backups, cleanups and reports all need to run reliably on a schedule without anyone logged in.
cron runs commands at times given by five fields: minute, hour, day of month, month, day of week, followed by the command. * means every value, */5 every fifth, 1-5 a range, 1,15 a list. So 30 2 * * * is 02:30 daily and */10 * * * 1-5 every ten minutes on weekdays. Edit your own table with crontab -e, list it with crontab -l; system jobs go in /etc/cron.d/ with an extra user field.
Cron jobs run with a minimal environment: a short PATH, no shell profile, the home directory as working directory. Use absolute paths, set variables at the top of the crontab or in the script, and redirect output (>> log 2>&1) or it is mailed to a mailbox nobody reads. Remember that % has a special meaning in crontab lines and must be escaped as \%.
systemd timers are the modern alternative: a .timer unit triggers a .service unit. Benefits: output goes to the journal, Persistent=true runs missed jobs after downtime, RandomizedDelaySec= spreads load, resource limits and dependencies apply, and systemctl list-timers shows next and last runs. OnCalendar= uses expressions like daily, Mon..Fri 09:00 or *-*-* 02:30:00; check them with systemd-analyze calendar. For a one-off delayed command, systemd-run --on-active=30m cmd or at work.
Example
crontab -e # edit YOUR crontab, lines like:
# m h dom mon dow command
# 30 2 * * * /home/ada/bin/backup.sh >> /home/ada/backup.log 2>&1
# */10 * * * 1-5 /usr/local/bin/check-queue
crontab -l # list it
# systemd alternative: /etc/systemd/system/backup.timer
# [Timer]
# OnCalendar=*-*-* 02:30:00
# Persistent=true # catch up if the machine was off
# [Install]
# WantedBy=timers.target
# ...plus backup.service with ExecStart=/home/ada/bin/backup.sh
sudo systemctl enable --now backup.timer
systemctl list-timers # next and last run of every timer
systemd-analyze calendar 'Mon..Fri 09:00' # when does this fire next?Remember
- Five cron fields: minute hour day-of-month month day-of-week
- Cron has a minimal environment: absolute paths and redirect output
- systemd timers add logging, catch-up runs and list-timers
Watch out for
- A script that works in your terminal but fails in cron because PATH or variables are missing.