X Xerobit

Cron Job Scheduling — How Cron Works and Best Practices

Cron runs scheduled tasks using 5-field time expressions. Learn how cron daemons work, how to manage crontabs, timezone handling, error logging, and alternatives like systemd...

Mian Ali Khalid · · 5 min read
Use the tool
Cron Builder
Build and parse cron expressions with human-readable explanations.
Open Cron Builder →

Cron is a time-based job scheduler in Unix/Linux. Understanding how the cron daemon works, where jobs run, and how to handle errors prevents silent failures and timezone bugs.

Use the Cron Builder to generate and validate cron expressions.

How cron works

┌─────────────────────────────────────────────────────────────────────┐
│ The cron daemon (crond) runs continuously                           │
│ Every minute it checks all crontab files                            │
│ If current time matches an entry → runs that job as its owner       │
└─────────────────────────────────────────────────────────────────────┘

Cron runs jobs in a minimal environment — $PATH is limited and $HOME may differ from your interactive session. Always use absolute paths.

Managing crontabs

# Edit your user's crontab:
crontab -e

# View your crontab:
crontab -l

# Remove your crontab:
crontab -r

# Edit another user's crontab (as root):
crontab -u username -e

# System-wide crontabs:
/etc/crontab           # System crontab (has extra username field)
/etc/cron.d/           # Drop-in cron files
/etc/cron.hourly/      # Scripts run every hour
/etc/cron.daily/       # Scripts run daily
/etc/cron.weekly/      # Scripts run weekly
/etc/cron.monthly/     # Scripts run monthly

Crontab format

# ┌────── minute (0-59)
# │ ┌──── hour (0-23)
# │ │ ┌── day of month (1-31)
# │ │ │ ┌ month (1-12)
# │ │ │ │ ┌ day of week (0-7, 0 and 7 are Sunday)
# │ │ │ │ │
# * * * * * command

# Run every minute:
* * * * * /path/to/script.sh

# Run at 2:30 AM daily:
30 2 * * * /opt/scripts/backup.sh

# Run every 15 minutes:
*/15 * * * * /opt/scripts/health-check.sh

# Run Monday-Friday at 9 AM:
0 9 * * 1-5 /opt/scripts/report.sh

# Run on the 1st of each month at midnight:
0 0 1 * * /opt/scripts/monthly-invoice.sh

System crontab format (extra user field)

# /etc/crontab has an extra user column:
# minute hour dom month dow user command
30 2 * * * root /opt/scripts/system-backup.sh

Always use absolute paths

# BAD: relies on $PATH which may not include /usr/local/bin:
*/5 * * * * python3 script.py

# GOOD: absolute paths everywhere:
*/5 * * * * /usr/bin/python3 /home/user/scripts/script.py

# Find full paths:
which python3   # /usr/bin/python3
which node      # /usr/local/bin/node

Error handling and logging

# Redirect stdout and stderr to a log file:
*/5 * * * * /opt/scripts/sync.sh >> /var/log/sync.log 2>&1

# Suppress all output (no email):
* * * * * /opt/scripts/noisy.sh > /dev/null 2>&1

# Log with timestamp:
*/5 * * * * echo "[$(date '+\%Y-\%m-\%d \%H:\%M:\%S')] Starting sync" >> /var/log/sync.log && /opt/scripts/sync.sh >> /var/log/sync.log 2>&1

# Rotate logs with logrotate (create /etc/logrotate.d/sync):
# /var/log/sync.log {
#   weekly
#   rotate 4
#   compress
#   missingok
# }

Timezone handling

# Cron uses system timezone by default
# Check system timezone:
timedatectl status

# Set timezone for specific cron job (GNU cron):
CRON_TZ=America/New_York
0 9 * * * /opt/scripts/report.sh

# Or use TZ variable in crontab file header:
TZ=UTC
0 0 * * * /opt/scripts/midnight-utc.sh

Lock file: prevent overlapping runs

If a job takes longer than its schedule interval:

# Flock prevents concurrent runs:
*/5 * * * * flock -n /tmp/sync.lock /opt/scripts/sync.sh

# Or with a custom lock check:
0 * * * * /bin/bash -c '[ -f /tmp/hourly.lock ] && exit 0; touch /tmp/hourly.lock; /opt/scripts/hourly.sh; rm /tmp/hourly.lock'

Alternatives to cron

# systemd timers (modern Linux alternative):
# More precise, better logging, dependencies, supports OnCalendar syntax
systemctl list-timers

# at — schedule one-time jobs:
echo "/opt/scripts/deploy.sh" | at 14:30

# Cloud schedulers:
# AWS EventBridge (CloudWatch Events) — cron or rate expressions
# Google Cloud Scheduler — cron syntax, HTTP/PubSub targets
# Azure Logic Apps — cron or interval

# Application-level:
# node-cron (Node.js)
# APScheduler (Python)
# Quartz (Java)
# Hangfire (.NET)

Related posts

Related tool

Cron Builder

Build and parse cron expressions with human-readable explanations.

Written by Mian Ali Khalid. Part of the Dev Productivity pillar.