Automating repetitive tasks is one of the core responsibilities of a Linux system administrator. Red Hat Enterprise Linux 8 provides several scheduling mechanisms: the venerable cron daemon for recurring jobs, anacron for machines that are not always running, the at command for one-off deferred tasks, and systemd timers for tighter integration with the service manager. Understanding when to reach for each tool — and how to configure it correctly — is essential for maintaining a healthy, self-managing server.
Prerequisites
- A running RHEL 8 system with root or sudo access
croniepackage installed and thecrondservice enabled (sudo dnf install -y cronie && sudo systemctl enable --now crond)- The
atcommand available (sudo dnf install -y at && sudo systemctl enable --now atd) - Basic familiarity with shell scripting
Step 1 — Schedule Recurring Jobs with crontab
The crontab -e command opens the current user’s crontab in the default editor. Each line follows the format: minute hour day-of-month month day-of-week command. Use * for “every” and commas or hyphens for lists and ranges.
# Edit the current user's crontab
crontab -e
# Example crontab entries:
# ┌─ minute (0-59)
# │ ┌─ hour (0-23)
# │ │ ┌─ day of month (1-31)
# │ │ │ ┌─ month (1-12)
# │ │ │ │ ┌─ day of week (0-7, 0 and 7 = Sunday)
# │ │ │ │ │
# Run a backup script every day at 02:30
30 2 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
# Run every 15 minutes
*/15 * * * * /usr/local/bin/check_disk.sh
# Run at 08:00 on weekdays (Mon-Fri)
0 8 * * 1-5 /usr/local/bin/send_report.sh
# List current user's crontab
crontab -l
# Edit root's crontab
sudo crontab -e -u root
Step 2 — Use System-wide Cron Drop-ins
For system jobs, prefer dropping a file into /etc/cron.d/ rather than editing root‘s crontab. Files in /etc/cron.d/ require an explicit username field and are managed as config files by RPM packages. The directories /etc/cron.hourly/, /etc/cron.daily/, /etc/cron.weekly/, and /etc/cron.monthly/ accept executable scripts that run at their respective intervals.
# Create a drop-in cron job (note the username field after the schedule)
sudo tee /etc/cron.d/db-cleanup <> /var/log/db_cleanup.log 2>&1
EOF
# Place an executable script for daily execution
sudo cp /usr/local/bin/log_rotate.sh /etc/cron.daily/log_rotate
sudo chmod +x /etc/cron.daily/log_rotate
# Test execution of a daily cron script immediately
sudo run-parts --test /etc/cron.daily/
Step 3 — Handle Missed Jobs with anacron
anacron is designed for systems that are not running continuously — laptops, VMs, or servers with maintenance windows. If a daily/weekly/monthly job was missed because the machine was off, anacron runs it after the next boot with a configurable delay. It is configured in /etc/anacrontab.
# View the anacron configuration
cat /etc/anacrontab
# Format: period delay job-id command
# period = days between runs
# delay = minutes to wait after boot before running
# Example entries:
# 1 5 cron.daily nice run-parts /etc/cron.daily
# 7 25 cron.weekly nice run-parts /etc/cron.weekly
# @monthly 45 cron.monthly nice run-parts /etc/cron.monthly
# Add a custom anacron job (run every 2 days, 10-min delay after boot)
sudo tee -a /etc/anacrontab << 'EOF'
2 10 custom-cleanup /usr/local/bin/cleanup.sh
EOF
# Check the anacron timestamp files (tracks last run)
ls -la /var/spool/anacron/
Step 4 — One-off Deferred Tasks with the at Command
The at command schedules a command to run once at a specified future time. It is ideal for maintenance tasks like a scheduled reboot or a one-time report that you need to run outside business hours.
# Schedule a command to run at 23:00 tonight
echo "/usr/local/bin/maintenance.sh" | at 23:00
# Schedule using relative time
echo "systemctl restart httpd" | at now + 30 minutes
echo "/usr/local/bin/report.sh" | at 08:00 tomorrow
echo "/usr/local/bin/deploy.sh" | at 14:00 2026-06-01
# List pending at jobs
atq
# View the contents of at job number 3
at -c 3
# Remove a pending at job
atrm 3
Step 5 — Modern Scheduling with systemd Timers
systemd timers are a powerful alternative to cron. They support calendar-based scheduling via OnCalendar, can be made persistent (catching up missed runs like anacron with Persistent=true), and integrate with journald for logging. Each timer requires a matching .service unit.
# Create the service unit
sudo tee /etc/systemd/system/backup.service << 'EOF'
[Unit]
Description=Daily Backup Job
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
EOF
# Create the timer unit
sudo tee /etc/systemd/system/backup.timer << 'EOF'
[Unit]
Description=Run backup.service daily at 02:30
[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true
Unit=backup.service
[Install]
WantedBy=timers.target
EOF
# Enable and start the timer
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
# List all active timers and their next trigger times
systemctl list-timers --all
Conclusion
You now have a complete picture of task scheduling on RHEL 8. Use crontab or /etc/cron.d/ drop-ins for straightforward recurring jobs, anacron to ensure daily and weekly jobs are not skipped on intermittent systems, at for one-off deferred execution, and systemd timers when you need tight logging integration or more robust missed-run handling. Always redirect cron job output to a log file so failures are visible, and test scripts manually before scheduling them.
Next steps: How to Monitor Disk Usage with df, du, lsblk and ncdu on RHEL 8, How to Use rsync for Efficient File Synchronisation on RHEL 8, and How to Write Bash Scripts for Automation on RHEL 8.