Cron, at & Automation
Intermediatecron runs commands on a schedule; at runs a command once at a specified future time. These are the standard Linux tools for backup jobs, report generation, and routine maintenance.
Overview
cron is a daemon that wakes up every minute and checks crontab files for commands to run. A crontab entry has five time fields (minute, hour, day, month, weekday) followed by the command. cron runs commands in a minimal environment — it does not source your .bashrc, so always use absolute paths. Systemd timers are the modern alternative (more features, journald logging, dependency management) but cron is still ubiquitous and worth knowing thoroughly.
Crontab Syntax
The five time fields control when the command runs. The asterisk * means "every". A common mistake is forgetting that cron runs in a minimal environment without your normal PATH.
# Crontab format:
# ┌──────────── minute (0 - 59)
# │ ┌────────── hour (0 - 23)
# │ │ ┌──────── day of month (1 - 31)
# │ │ │ ┌────── month (1 - 12)
# │ │ │ │ ┌──── day of week (0=Sun, 6=Sat, 7=Sun)
# │ │ │ │ │
# * * * * * command to execute
# Examples:
* * * * * /opt/scripts/heartbeat.sh # every minute
0 * * * * /opt/scripts/hourly-report.sh # every hour at :00
0 2 * * * /opt/scripts/backup.sh # daily at 2:00 AM
0 2 * * 0 /opt/scripts/weekly-cleanup.sh # Sundays at 2:00 AM
0 0 1 * * /opt/scripts/monthly-invoice.sh # 1st of every month, midnight
*/5 * * * * /opt/scripts/health-check.sh # every 5 minutes
0 9-17 * * 1-5 /opt/scripts/business-hours.sh # every hour, 9-5, Mon-Fri
# Shortcuts
@reboot /opt/scripts/startup.sh # on system boot
@daily /opt/scripts/backup.sh # same as: 0 0 * * *
@weekly /opt/scripts/cleanup.sh # same as: 0 0 * * 0
@monthly /opt/scripts/report.sh # same as: 0 0 1 * *
# crontab.guru — visual cron expression editor onlineManaging Crontabs
Each user has their own crontab. System-wide crontabs live in /etc/cron.d/. Cron runs in a minimal shell environment — always use absolute paths and set PATH explicitly.
# Edit your crontab
crontab -e # opens in $EDITOR (usually nano or vi)
crontab -l # list current crontab
crontab -r # remove crontab âš ï¸ no confirmation!
# Root crontab (for system tasks)
sudo crontab -e
sudo crontab -l
# System crontab locations:
# /etc/crontab → system-wide crontab (has extra 'user' field)
# /etc/cron.d/ → drop-in crontab files
# /etc/cron.daily/ → scripts run daily
# /etc/cron.hourly/ → scripts run hourly
# Example: /etc/cron.d/myapp
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=admin@company.com # email output to admin (empty = no email)
0 2 * * * appuser /opt/myapp/scripts/backup.sh >> /var/log/myapp-backup.log 2>&1
# Common cron pitfalls:
# 1. PATH is minimal — use absolute paths: /usr/bin/python3 not python3
# 2. No home directory expansion — use $HOME or /home/user explicitly
# 3. Output goes to email (MAILTO) or is discarded — redirect to log file
# 4. % is special in crontab — escape with % or use a script file
# Verify cron is running
systemctl status cron # Debian/Ubuntu
systemctl status crond # RHEL/CentOSSystemd Timers — Modern Alternative
Systemd timers replace cron for new deployments: they use journald for logging, support dependencies, and can be activated relative to system events.
# Two files needed: a .timer unit and a .service unit
# /etc/systemd/system/backup.service
[Unit]
Description=Daily database backup
After=postgresql.service
[Service]
Type=oneshot # exits when done (not a daemon)
User=postgres
ExecStart=/opt/scripts/backup.sh
StandardOutput=journal
StandardError=journal
# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup daily at 2 AM
[Timer]
OnCalendar=*-*-* 02:00:00 # daily at 2 AM (systemd calendar syntax)
# OnCalendar=weekly # shorthand: weekly on Monday 00:00
# OnBootSec=5min # 5 minutes after boot
# OnUnitActiveSec=1h # 1 hour after last activation
Persistent=true # run immediately if last run was missed
[Install]
WantedBy=timers.target
# Deploy
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
# Manage
systemctl list-timers # show all timers and next run time
systemctl status backup.timer
journalctl -u backup.service # logs from timer-triggered runs
systemctl start backup.service # trigger manually for testingKey Points to Remember
- 1Crontab fields: minute hour day month weekday — remember with "minute or hour, day or month, weekday".
- 2Always use absolute paths in crontab — cron runs with a minimal PATH.
- 3Redirect cron job output to a log file: command >> /var/log/job.log 2>&1.
- 4@reboot runs a command once at system startup — useful for background services.
- 5Systemd timers offer journald logging, dependency management, and catch-up on missed runs.
- 6crontab.guru is the fastest way to verify a cron expression.
Interview Questions
Sign in to ask AriaHow do you run a cron job every 5 minutes?
A cron job works when run manually but fails when run by cron. Why?
Ask Aria about Cron, at & Automation
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.