G
GuideDevOps
Lesson 17 of 17

Cron Jobs & Scheduling

Part of the Linux Fundamentals tutorial series.

Time-Based Scheduling

The cron daemon is Linux's built-in job scheduler. It runs commands automatically at specified times — backups, health checks, log rotation, report generation.

# Check if cron is running
$ systemctl status cron
 cron.service - Regular background program processing daemon
   Loaded: loaded (/lib/systemd/system/cron.service; enabled)
   Active: active (running) since Thu 2026-04-10 08:00:00 UTC; 3h ago

Managing Cron Jobs

Crontab Syntax

The crontab (cron table) defines scheduled tasks.

# Edit the current user's crontab
$ crontab -e
 
# List the current user's cron jobs
$ crontab -l
# No crontab for admin
 
# Edit another user's crontab
$ sudo crontab -u alice -e
 
# Remove all cron jobs for current user
$ crontab -r

Crontab Format

┌───────────── minute (0-59)
│ ┌───────────── hour (0-23)
│ │ ┌───────────── day of month (1-31)
│ │ │ ┌───────────── month (1-12)
│ │ │ │ ┌───────────── day of week (0-6, Sunday=0)
│ │ │ │ │
│ │ │ │ │
* * * * * command

Crontab Syntax Examples

# ┌───────────── minute (0-59)
# │ ┌───────────── hour (0-23)
# │ │ ┌───────────── day of month (1-31)
# │ │ │ ┌───────────── month (1-12)
# │ │ │ │ ┌───────────── day of week (0-6, Sunday=0)
# │ │ │ │ │
# │ │ │ │ │
* * * * * /opt/scripts/health-check.sh
FieldAllowed Values
minute0-59
hour0-23
day of month1-31
month1-12
day of week0-6 (Sunday=0)

Real-World Crontab Examples

# Run every minute
* * * * * /opt/scripts/monitor.sh
 
# Run every 5 minutes
*/5 * * * * /opt/scripts/health-check.sh
 
# Run every hour (at minute 0)
0 * * * * /opt/scripts/hourly-report.sh
 
# Run daily at 2:00 AM (backup time — low traffic)
0 2 * * * /opt/scripts/backup.sh
 
# Run daily at midnight
0 0 * * * /opt/scripts/daily-cleanup.sh
 
# Run every Monday at 8:30 AM
30 8 * * 1 /opt/scripts/weekly-report.sh
 
# Run on the 1st of every month at 3:00 AM
0 3 1 * * /opt/scripts/monthly-archive.sh
 
# Run every 15 minutes during business hours (9 AM - 5 PM)
*/15 9-17 * * 1-5 /opt/scripts/business-hours-task.sh
 
# Run every 30 minutes every day
*/30 * * * * /opt/scripts/30min-task.sh

Special Keywords

# Instead of the 5-field syntax, you can use these:
@reboot    /opt/scripts/startup.sh        # Run once at reboot
@yearly    /opt/scripts/annual.sh         # Run once a year (Jan 1, 00:00)
@monthly   /opt/scripts/monthly.sh       # Run once a month (1st, 00:00)
@weekly    /opt/scripts/weekly.sh         # Run once a week (Sunday, 00:00)
@daily     /opt/scripts/daily.sh          # Run once a day (midnight)
@hourly    /opt/scripts/hourly.sh        # Run once an hour

Cron Environment

Cron runs in a minimal environment. Variables like $PATH and $HOME may differ from your interactive shell.

# In crontab, always use absolute paths or set PATH
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
 
# Use absolute paths for commands
0 2 * * * /usr/bin/python3 /opt/scripts/backup.py
 
# Redirect output to a log file
0 2 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1
 
# Mail results to a specific address (if mail is configured)
MAILTO=ops@example.com
0 2 * * * /opt/scripts/backup.sh

System Cron Jobs

Beyond user crontabs, the system has its own scheduled jobs in these locations:

# System-wide cron directories (run as root)
$ ls /etc/cron.d/
php8.1-cli Package-installed cron jobs
logrotate Log rotation schedule
 
# Timed directories (replace cron for some tasks)
$ ls /etc/cron.daily/
0anacron  apt-compat  chromium  dpkg  logrotate  man-db
 
$ ls /etc/cron.hourly/
0anacron  php8.1-fpm
 
# User crontabs are stored here
$ ls /var/spool/cron/crontabs/
alice  bob

anacron — For Non-Continuously Running Systems

cron doesn't run jobs that were missed while the system was off. anacron handles this for daily/weekly/monthly tasks on laptops and servers that aren't always on.

$ cat /etc/anacrontab
# /etc/anacrontab: configuration file for anacron
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/bin
# period  delay  job-identifier  command
1    5    cron.daily    run-parts /etc/cron.daily
7    10   cron.weekly   run-parts /etc/cron.weekly
@monthly 15  cron.monthly run-parts /etc/cron.monthly

Monitoring Cron

# Check system logs for cron execution
$ grep CRON /var/log/syslog | tail -20
Apr 10 14:00:01 server CRON[12345]: (admin) CMD (/opt/scripts/health-check.sh)
Apr 10 14:05:01 server CRON[12346]: (admin) CMD (/opt/scripts/monitor.sh)
Apr 10 14:10:01 server CRON[12347]: (root) CMD (test -x /usr/sbin/anacron)
 
# Cron job output is emailed to the user by default
# Check local mail
$ mail
Mail version 8.1.2 01/15/2023.

Quick Reference

ScheduleCrontab Entry
Every minute* * * * *
Every 5 minutes*/5 * * * *
Every hour0 * * * *
Daily at 2 AM0 2 * * *
Weekly on Monday0 8 * * 1
Monthly on 1st0 3 1 * *
Every 15 min (9-5)*/15 9-17 * * 1-5
TaskCommand
Edit crontabcrontab -e
List crontabcrontab -l
Remove crontabcrontab -r
Edit user's crontabsudo crontab -u user -e

Practice Challenge

  1. Run crontab -l to check if you have any existing cron jobs
  2. Add a cron job that runs echo "Cron ran at $(date)" >> /tmp/cron-test.log every minute
  3. Watch the log file with tail -f /tmp/cron-test.log to confirm it runs
  4. Remove the test cron job with crontab -r
  5. List the contents of /etc/cron.daily/ — what scheduled tasks does your system run?
  6. Check /var/log/syslog for CRON entries: grep CRON /var/log/syslog | tail -10