Master cron syntax, common expressions, and best practices for scheduling tasks in Linux, Docker, and cloud environments.
Cron is a time-based job scheduler built into Unix-like systems. It allows you to run commands or scripts automatically at specified intervals — from every minute to once a year.
The name comes from Chronos, the Greek god of time. The daemon that runs in the background is called crond, and the configuration files are called crontabs (cron tables).
A cron expression has five fields separated by spaces:
┌───────────── minute (0–59)
│ ┌─────────── hour (0–23)
│ │ ┌───────── day of month (1–31)
│ │ │ ┌─────── month (1–12)
│ │ │ │ ┌───── day of week (0–6, Sunday=0)
│ │ │ │ │
* * * * * command to run
| Character | Meaning | Example |
|---|---|---|
* | Any value | * * * * * — every minute |
, | List separator | 1,15,30 * * * * — at minutes 1, 15, and 30 |
- | Range | 9-17 * * * * — every minute from 9am to 5pm |
*/n | Step | */5 * * * * — every 5 minutes |
@hourly | Shorthand | Same as 0 * * * * |
Here are the most frequently used cron expressions:
# Every minute
* * * * * /path/to/script.sh
# Every hour at :30
30 * * * * /scripts/hourly-task.sh
# Every day at midnight
0 0 * * * /scripts/daily-backup.sh
# Every Monday at 9 AM
0 9 * * 1 /scripts/weekly-report.sh
# Every weekday (Mon–Fri) at 8 AM
0 8 * * 1-5 /scripts/business-hours.sh
# First day of every month at 2 AM
0 2 1 * * /scripts/monthly-cleanup.sh
# Every 15 minutes
*/15 * * * * /scripts/health-check.sh
Most cron implementations support these convenient aliases:
| Shorthand | Equivalent | Description |
|---|---|---|
@yearly | 0 0 1 1 * | Once a year, January 1 |
@monthly | 0 0 1 * * | Once a month, first day |
@weekly | 0 0 * * 0 | Once a week, Sunday midnight |
@daily | 0 0 * * * | Once a day at midnight |
@hourly | 0 * * * * | Once an hour |
@reboot | — | At system startup |
# Edit your crontab
crontab -e
# List your crontab
crontab -l
# Remove your crontab
crontab -r
# Edit another user's crontab (root only)
crontab -u username -e
Cron jobs fail silently by default. Always redirect output:
# Redirect stdout and stderr to a log file
0 2 * * * /scripts/backup.sh >> /var/log/backup.log 2>&1
# Discard all output
0 2 * * * /scripts/noisy-script.sh > /dev/null 2>&1
# Check cron logs on systemd systems
journalctl -u cron
grep CRON /var/log/syslog
In containerized environments, cron has quirks:
Docker: Add cron to your Dockerfile and ensure it runs as a foreground process.
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y cron
COPY crontab /etc/cron.d/my-cron
RUN chmod 0644 /etc/cron.d/my-cron && crontab /etc/cron.d/my-cron
CMD ["cron", "-f"]
Kubernetes: Use CronJob resources instead of system cron:
apiVersion: batch/v1
kind: CronJob
metadata:
name: daily-backup
spec:
schedule: "0 2 * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: backup-tool:latest
restartPolicy: OnFailure
When you don't want to manage cron infrastructure:
schedule with cron syntax for CI/CD workflows$PATH. Always use full paths: /usr/bin/python3 not python3./etc/cron.d/ should specify the user: 0 2 * * * root /scripts/backup.sh.cronic or similar wrappers.flock to prevent a long-running job from starting again before it finishes:*/5 * * * * flock -n /tmp/my-script.lock /scripts/my-script.sh
Cron is simple but powerful. The key is getting the expression syntax right — use HeoLab's Cron Expression Parser to visually verify your schedule and preview the next 5 run times before deploying.