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...
Use the tool
Cron Builder
Build and parse cron expressions with human-readable explanations.
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 tools
- Cron Builder — build and validate cron expressions
- Cron Expression Guide — cron field syntax reference
Related posts
- Cron Expression Syntax, Explained by Field — Five fields, nine special characters, a dozen edge cases. A complete reference f…
- Cron Pitfalls: Timezones, DST, and Missed Runs — Your cron job will run twice or skip entirely when DST changes. Here's why, how …
- AWS EventBridge Scheduler — Cron Schedules for Lambda and AWS Services — AWS EventBridge Scheduler runs Lambda functions, ECS tasks, and other AWS target…
- Cron Expression Guide — Syntax, Fields, and Special Characters — Cron expressions schedule recurring jobs using five or six fields: minute, hour,…
- GitHub Actions Scheduled Workflows — cron Syntax and Examples — Schedule GitHub Actions workflows with cron expressions using the schedule trigg…
Related tool
Cron Builder
Build and parse cron expressions with human-readable explanations.
Written by Mian Ali Khalid. Part of the Dev Productivity pillar.