Cron is the silent scheduler behind most automated infrastructure. It controls when backups run, when logs rotate, when health checks fire, and when reports get generated. But the expression syntax — five terse fields packed with asterisks, slashes, and commas — trips up even experienced engineers. This guide breaks the format down field by field (with copy-paste examples for the schedules developers need most), or you can use our visual Cron Job Generator to build and validate cron expressions 100% locally in your browser.
What is Cron? A Brief History
Originating in Version 7 Unix in 1979, cron was designed to be a time-based job scheduler. The name cron comes from the Greek word for time, chronos. Today, it remains the standard for task automation across Unix-like operating systems, macOS, and even modern containerized environments like Kubernetes (CronJobs).
A cron service (typically a daemon named crond) wakes up every minute, checks a configuration file (the crontab) for tasks scheduled for the current minute, and executes them in the background. The beauty of cron lies in its simplicity and reliability.
The Crontab File and Basic Commands
The configuration file where cron jobs are stored is called a crontab (cron table). Each user on a Unix system can have their own crontab, and there is also a system-wide crontab (usually located at /etc/crontab).
Here are the essential terminal commands you need to manage your cron jobs:
1. Edit Your Crontab
crontab -e Expected Output: Opens your default terminal text editor (like vim or nano). If it's your first time, you may be prompted to choose an editor:
no crontab for user - using an empty one
Select an editor. To change later, run 'select-editor'.
1. /bin/nano <---- easiest
2. /usr/bin/vim.basic
3. /usr/bin/vim.tiny
4. /bin/ed
Choose 1-4 [1]: 2. List Your Cron Jobs
crontab -l Expected Output: Prints the contents of your crontab to standard output.
# Edit this file to introduce tasks to be run by cron.
*/5 * * * * /usr/local/bin/healthcheck.sh
0 0 * * * /scripts/daily_backup.sh 3. Remove Your Crontab
crontab -r Warning: This deletes your crontab entirely without confirmation. Always use crontab -i (interactive mode) to get a prompt before deletion.
The Five Fields in Detail
Every standard cron expression has exactly five fields, read left to right:
┌───────── minute (0–59)
│ ┌─────── hour (0–23)
│ │ ┌───── day of month (1–31)
│ │ │ ┌─── month (1–12)
│ │ │ │ ┌─ day of week (0–7, 0 and 7 = Sunday)
│ │ │ │ │
* * * * *
Each field accepts a number, a wildcard (* = every), a range (1-5), a list (1,3,5), or a step value (*/10 = every 10th).
Field 1: Minute (0 - 59)
Determines the exact minute of the hour the job runs. 15 means the 15th minute.
Field 2: Hour (0 - 23)
Determines the hour of the day in 24-hour format. 0 is midnight, 14 is 2 PM.
Field 3: Day of the Month (1 - 31)
Determines the date. 1 is the first day of the month.
Field 4: Month (1 - 12)
Determines the month. You can also use three-letter abbreviations like JAN, FEB.
Field 5: Day of the Week (0 - 7)
Determines the weekday. 0 and 7 both represent Sunday. You can use abbreviations like SUN, MON.
Standard Cron Schedules With Examples
Every 5 Minutes
*/5 * * * * /scripts/poll_queue.sh
The */5 in the minute field means "at minute 0, 5, 10, 15…55." The remaining wildcards let it run every hour, every day. This is the most searched cron pattern — useful for health checks, queue workers, and lightweight polling tasks.
Every Day at Midnight
0 0 * * * /scripts/database_dump.sh Runs once at 00:00 server time. Common for log rotation, database dumps, and cleanup scripts.
Every Monday at 9 AM
0 9 * * 1 /scripts/weekly_report.sh The 1 in the weekday field means Monday. Useful for weekly report generation or sprint-start notifications.
First Day of Every Month at 6 AM
0 6 1 * * /scripts/billing_cycle.sh The 1 in the day-of-month field triggers on the first. Great for billing summaries and monthly audit exports.
Every Weekday During Business Hours
0 9-17 * * 1-5 /scripts/active_monitor.sh Runs at the top of the hour from 9 AM to 5 PM, Monday through Friday.
Advanced Workarounds
Every 30 Seconds (Sub-minute Workaround)
Standard cron doesn't support sub-minute intervals. The common workaround is two entries offset by 30 seconds using sleep in the command itself:
* * * * * /path/to/script.sh
* * * * * sleep 30 && /path/to/script.sh Special Characters Quick Reference
| Character | Meaning | Example |
|---|---|---|
* | Every value | * * * * * = every minute |
*/n | Every nth value | */15 * * * * = every 15 min |
a-b | Range | 0 9-17 * * * = hourly 9AM–5PM |
a,b | List | 0 6,18 * * * = 6AM and 6PM |
L | Last day (extended cron only) | 0 0 L * * = Last day of the month |
W | Nearest weekday (extended cron) | 0 0 15W * * = Nearest weekday to 15th |
Note: L and W are not supported in all cron implementations. They are supported in Quartz scheduler and some modern cron daemons.
Cron Environment Variables
By default, cron runs in a highly restricted environment. This is a massive source of bugs for beginners.
When you run a command in your terminal, it has access to your full PATH. Cron usually only has PATH=/usr/bin:/bin. If your script relies on Node, Python, or custom binaries, it might fail.
Solution 1: Define PATH in crontab
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
0 * * * * node /app/script.js Solution 2: Use Absolute Paths
0 * * * * /usr/local/bin/node /app/script.js Output Redirection and Logging
If a cron job fails, where do the logs go? By default, cron tries to email them to the user. To log output to a file, use shell redirection:
# Log stdout to backup.log, discard stderr
0 2 * * * /scripts/backup.sh > /var/log/backup.log
# Log both stdout and stderr to the same file
0 2 * * * /scripts/backup.sh > /var/log/backup.log 2>&1
# Discard all output entirely
0 2 * * * /scripts/backup.sh > /dev/null 2>&1 Troubleshooting Common Errors
1. Command Not Found
Symptom: The job doesn't run, and logs show /bin/sh: 1: command not found.
Fix: As mentioned above, cron runs with a minimal environment. Provide the absolute path to your executable (e.g., /usr/bin/python3 instead of python3).
2. Permission Denied
Symptom: /bin/sh: 1: /path/to/script: Permission denied.
Fix: Make your script executable via chmod +x /path/to/script.
3. The Percent Sign (%) Issue
Symptom: Using date +%Y%m%d in a cron command causes it to truncate or fail.
Fix: In crontabs, the percent sign % is a special character used for newlines. You must escape it with a backslash: date +\%Y\%m\%d.
4. Silent Failures
Symptom: The cron job doesn't seem to execute and produces no logs.
Fix: Check the system cron logs (usually at /var/log/cron or via grep CRON /var/log/syslog). Also, make sure your crontab file ends with a blank newline character, or the last job might be ignored.
Cron vs. Systemd Timers
In modern Linux distributions, Systemd Timers (which you can build effortlessly using a Systemd Timer Generator) have largely replaced cron for system-level scheduled tasks. Here is a comparison:
| Feature | Cron | Systemd Timers |
|---|---|---|
| Syntax | Concise 5-field expression | Verbose unit files |
| Sub-minute Intervals | ❌ No (requires workarounds) | ✅ Yes (microseconds supported) |
| Logging | Relies on email or basic redirection | ✅ Integrated with journalctl |
| Missed Job Catchup | ❌ No (unless using anacron) | ✅ Yes (Persistent=true) |
For simple user scripts and basic automation, cron is still king due to its ubiquity and ease of use.
Common Mistakes
- Forgetting timezone. Cron uses server time unless explicitly configured. An AWS Lambda cron in UTC will fire at a different wall-clock time than a local crontab. Always double-check your server timezone with the
datecommand. - Day-of-month AND day-of-week. Setting both fields creates an OR condition, not AND.
0 0 15 * 1runs on the 15th AND every Monday — not just Mondays that fall on the 15th. - Using
0vs7for Sunday. Both are valid, but mixing them in the same team or config set leads to confusion. Pick one and stick with it.
Build It Visually
If you'd rather build and preview cron expressions without memorizing the syntax, try the Cron Job Generator (or if you need to decipher an existing schedule, use our Crontab Translator). It shows the next scheduled run times in real time, runs entirely in your browser, and doesn't upload anything.
Frequently Asked Questions
- What is a cron expression?
- A cron expression is a string of five (or six) fields separated by spaces that tells a scheduler exactly when to run a task. The fields represent minute, hour, day of month, month, and day of week.
- How do I write a cron expression for every 5 minutes?
- Use
*/5 * * * *— the*/5in the minute field means "every 5th minute", and the wildcards mean "every hour, every day, every month, every weekday." - What does the asterisk mean in cron?
- An asterisk (
*) means "every possible value" for that field. For example,*in the hour field means every hour. - Can I test cron expressions without deploying?
- Yes. Use a browser-based cron expression generator to build, validate, and preview the next run times before adding the expression to your system.
- How do I edit my cron jobs?
- Open your terminal and run
crontab -eto edit your personal user crontab. Save and exit the editor to apply the new schedule automatically.