Cron Expression Builder Guide: Create Scheduled Tasks Like a Pro

DevToolkit Team · · 14 min read

If you have ever needed to run a script at 2 AM every Sunday, send a report on the first business day of each month, or purge temp files every fifteen minutes, you have encountered cron. The tiny scheduling daemon that ships with every Unix and Linux system has been quietly running the internet's background tasks since the 1970s — and its five-field expression syntax remains the lingua franca of scheduled automation everywhere from bare-metal servers to Kubernetes, GitHub Actions, and AWS CloudWatch.

The problem? Cron syntax is terse. Writing 15 3 1-7 * 1 from memory and trusting it will fire on the first Monday of the month takes confidence most of us do not have. That is exactly why a cron expression builder exists — a visual tool that lets you pick the schedule you want and translates it into a valid cron string instantly.

In this comprehensive cron expression builder guide, you will learn the five-field syntax inside and out, master every special character, walk through a step-by-step builder workflow using our free cron expression generator, explore cron in CI/CD pipelines, and pick up debugging and timezone tips that will save you hours of frustration.

What Is Cron and Why Does It Matter?

Cron is a time-based job scheduler found in Unix-like operating systems. The name comes from the Greek word chronos (time). A cron job is any command or script that cron runs on a recurring schedule you define with a cron expression.

Cron matters because scheduled automation is everywhere:

Any time you hear "run this every…" the answer almost always involves a cron expression.

The 5-Field Cron Syntax Explained

A standard cron expression consists of five fields separated by spaces. Each field constrains when the job fires:

┌───────────── minute       (0–59)
│ ┌───────────── hour         (0–23)
│ │ ┌───────────── day of month (1–31)
│ │ │ ┌───────────── month       (1–12 or JAN–DEC)
│ │ │ │ ┌───────────── day of week  (0–7 or SUN–SAT; 0 and 7 both = Sunday)
│ │ │ │ │
* * * * *

The cron daemon evaluates all five fields against the current system time every minute. When every field matches, the associated command runs. Think of it as a logical AND across all five conditions.

Field Reference Table

Field Position Allowed Values Allowed Special Characters
Minute 1st 0–59 * , - /
Hour 2nd 0–23 * , - /
Day of Month 3rd 1–31 * , - /
Month 4th 1–12 or JAN–DEC * , - /
Day of Week 5th 0–7 or SUN–SAT * , - /

Tip: Some implementations (Quartz, Spring, AWS EventBridge) add a sixth seconds field at the beginning or a year field at the end. Always check your platform's documentation. For the standard Unix crontab, five fields is all you need.

Special Characters in Cron Expressions

Four special characters give cron expressions their flexibility. Mastering them is the key to building any schedule without a cron expression builder — though a builder is still handy for verification.

Asterisk (*) — Any Value

The wildcard matches every possible value for a field. * * * * * means "every minute of every hour of every day of every month on every day of the week" — in other words, every single minute.

Comma (,) — List

Specifies a list of discrete values. 0 8,12,18 * * * fires at 8:00 AM, 12:00 PM, and 6:00 PM every day. You can list as many values as you need, separated by commas with no spaces.

Hyphen (-) — Range

Defines an inclusive range. 0 9-17 * * 1-5 fires at the top of every hour from 9 AM to 5 PM, Monday through Friday. Ranges are cleaner than writing out every value with commas.

Slash (/) — Step

Specifies an interval. */10 * * * * means "every 10 minutes." You can combine a starting value with a step: 5/15 * * * * fires at minutes 5, 20, 35, and 50. The slash is the most powerful character for building recurring schedules.

Non-Standard Characters

CharacterMeaningSupported ByExample
LLast day of month or last X day of weekQuartz, Spring0 0 L * * — last day of month
WNearest weekday to given dayQuartz, Spring0 0 15W * * — nearest weekday to 15th
#Nth occurrence of a weekday in monthQuartz, Spring0 0 * * 5#3 — third Friday
?No specific value (either day-of-month or day-of-week)Quartz, AWS0 12 ? * MON — noon every Monday

Standard Unix crontab does not support L, W, #, or ?. If your target system is a plain Linux crontab, stick to * , - /.

Common Cron Schedule Examples

Here is a reference library of the schedules developers need most often. Bookmark this section or check our cron expression cheat sheet for even more patterns.

Every X Minutes

* * * * *        # Every minute
*/5 * * * *      # Every 5 minutes
*/10 * * * *     # Every 10 minutes
*/15 * * * *     # Every 15 minutes
*/30 * * * *     # Every 30 minutes

Hourly Schedules

0 * * * *        # Every hour at minute 0
30 * * * *       # Every hour at minute 30
0 */2 * * *      # Every 2 hours
0 */6 * * *      # Every 6 hours

Daily Schedules

0 0 * * *        # Midnight every day
0 6 * * *        # 6:00 AM every day
30 8 * * *       # 8:30 AM every day
0 22 * * *       # 10:00 PM every day

Weekly Schedules

0 0 * * 0        # Midnight every Sunday
0 9 * * 1        # 9:00 AM every Monday
0 17 * * 5       # 5:00 PM every Friday
0 10 * * 1-5     # 10:00 AM every weekday (Mon–Fri)

Monthly Schedules

0 0 1 * *        # Midnight on the 1st of every month
0 9 15 * *       # 9:00 AM on the 15th of every month
0 0 1 1 *        # Midnight on January 1st (yearly)
0 0 1 */3 *      # Midnight on the 1st, every 3 months (quarterly)

Business-Oriented Schedules

0 9 * * 1-5      # 9 AM weekdays — morning standup trigger
0 0 1,15 * *     # Midnight on 1st and 15th — bi-monthly payroll
0 3 * * 0        # 3 AM Sunday — weekly database maintenance
*/5 9-17 * * 1-5 # Every 5 min during business hours, weekdays only

Using a Cron Expression Builder: Step-by-Step

While you can certainly hand-write cron expressions, a cron expression builder tool eliminates guesswork and catches mistakes before they reach production. Here is how to use our free online cron generator step by step.

Step 1: Open the Builder

Navigate to the DevToolkit Cron Generator. You will see dropdown menus or input fields for each of the five cron fields: minute, hour, day of month, month, and day of week.

Step 2: Select the Frequency

Start with the broadest frequency that matches your requirement. Do you need something every few minutes, hourly, daily, weekly, or monthly? Many builders offer preset buttons for these common frequencies to get you started quickly.

Step 3: Customize Each Field

Fine-tune the individual fields. For example, if you want a job at 8:30 AM every weekday:

The builder instantly shows you the resulting expression: 30 8 * * 1-5.

Step 4: Review the Human-Readable Description

Good cron builders display a plain-English translation of your expression, such as "At 08:30 AM, Monday through Friday." Read this carefully — it is much easier to spot a mistake in English than in cron syntax.

Step 5: Preview the Next Run Times

Most builders show the next 5–10 execution times based on the current date. This is the most reliable verification: if the next run times match your expectations, the expression is correct. Pay attention to timezone settings — more on that below.

Step 6: Copy and Deploy

Copy the generated expression and paste it into your crontab, CI/CD config, or cloud scheduler. Always test in a staging environment before deploying to production.

Managing Crontab on Linux and macOS

Once you have built your cron expression, you need to install it in the system's cron scheduler. The crontab command is the standard interface.

Essential Crontab Commands

# View your current crontab
crontab -l

# Edit your crontab (opens in $EDITOR)
crontab -e

# Remove your entire crontab (use with extreme caution!)
crontab -r

# Edit another user's crontab (requires root)
sudo crontab -u username -e

Crontab File Format

Each line in a crontab file follows this structure:

# Environment variables (optional)
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
[email protected]

# Schedule entries
# min hour dom month dow command
0 3 * * * /home/user/scripts/backup.sh >> /var/log/backup.log 2>&1
*/5 * * * * /usr/bin/curl -s https://example.com/health > /dev/null
0 9 * * 1 /home/user/scripts/weekly-report.py

Pro tip: Always redirect output with >> logfile 2>&1 so you have a trail to debug when things go wrong. Without redirection, cron emails the output to the user's local mailbox — which most people never check.

System-Wide Cron Directories

In addition to per-user crontabs, Linux distributions provide system-wide cron directories:

To use these directories, simply place an executable script inside them. No cron expression needed — the scheduling is handled by the directory name.

Cron Expressions in CI/CD Pipelines

Modern DevOps heavily leverages cron expressions outside of traditional crontab. Here is how cron syntax appears in popular CI/CD platforms.

GitHub Actions

GitHub Actions uses the schedule trigger with standard 5-field cron expressions. All times are in UTC.

name: Nightly Build
on:
  schedule:
    - cron: '0 3 * * *'   # 3:00 AM UTC every day
    - cron: '0 12 * * 1'  # Noon UTC every Monday

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm run build && npm test

Important: GitHub Actions scheduled workflows can be delayed during periods of high load. Do not rely on them for time-critical operations. Also note that scheduled workflows only run on the default branch.

GitLab CI/CD

GitLab supports pipeline schedules configured through the UI or API. The cron syntax is identical to standard five-field expressions:

# In GitLab UI: Pipeline Schedules → New Schedule
# Cron: 0 2 * * *
# Timezone: America/New_York
# Target branch: main

Jenkins

Jenkins uses a cron-like syntax in the triggers block. It adds a special H symbol that distributes load by hashing the job name:

pipeline {
    triggers {
        cron('H 3 * * *')  // Sometime during the 3 AM hour
    {
    stages {
        stage('Build') {
            steps {
                sh 'make build'
            {
        {
    {
{

AWS CloudWatch Events / EventBridge

AWS uses a six-field cron format that adds a year field and uses ? for either day-of-month or day-of-week:

# AWS cron format: minute hour day-of-month month day-of-week year
cron(0 3 * * ? *)       # 3 AM UTC every day
cron(0 12 ? * MON-FRI *) # Noon UTC weekdays
cron(0 0 1 * ? *)       # Midnight on the 1st of every month

Notice the ? character — AWS requires it in either the day-of-month or day-of-week field. Use our cron expression builder to generate the correct format for your target platform.

Kubernetes CronJobs

Kubernetes CronJobs use standard five-field cron syntax in YAML manifests:

apiVersion: batch/v1
kind: CronJob
metadata:
  name: database-backup
spec:
  schedule: "0 2 * * *"  # 2 AM daily
  concurrencyPolicy: Forbid
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: backup
            image: backup-tool:latest
            command: ["./run-backup.sh"]
          restartPolicy: OnFailure

Debugging Cron Jobs: Why Your Job Did Not Run

Cron jobs fail silently more often than any other part of a system. Here is a systematic checklist for debugging.

1. Check the Expression

Paste your cron expression into a cron expression builder and verify the next run times. A surprisingly common mistake is swapping the day-of-month and month fields, or using 24-hour time incorrectly (there is no hour 24 — midnight is 0).

2. Inspect the Cron Log

# On most Linux systems
grep CRON /var/log/syslog

# On CentOS/RHEL
grep CRON /var/log/cron

# On macOS
log show --predicate 'process == "cron"' --last 1h

The cron log tells you whether cron attempted to execute your command. If you see no entry at the expected time, the expression itself is wrong or the cron daemon is not running.

3. Verify the Environment

Cron runs commands in a minimal environment. Your shell profile (~/.bashrc, ~/.zshrc) is not loaded. Common issues include:

4. Check Permissions

Ensure the script is executable (chmod +x script.sh) and that the cron user has permission to access all files and directories the script touches. Also verify the user is not in /etc/cron.deny.

5. Capture Output

Always redirect both stdout and stderr to a log file:

0 3 * * * /home/user/backup.sh >> /home/user/logs/backup.log 2>&1

Without this redirection, errors vanish into the void (or an unread local mailbox). This is the single most important debugging practice for cron jobs.

6. Test Manually First

Before scheduling, run the exact command that cron will execute in a clean shell. Simulate cron's minimal environment:

env -i HOME=$HOME SHELL=/bin/bash /bin/bash -c '/home/user/scripts/backup.sh'

If the command fails here, it will fail in cron too.

Timezone Considerations for Cron

Timezone handling is one of the most treacherous aspects of cron scheduling. Get it wrong and your 3 AM backup runs at 3 PM — or not at all when daylight saving time shifts.

System Crontab

Traditional crontab uses the system timezone (whatever timedatectl or /etc/timezone reports). If your server is set to UTC but you want jobs to run at 9 AM Eastern, you must manually convert: 9 AM ET is 14:00 UTC (or 13:00 during EDT). This is error-prone.

Per-Job Timezone (Modern Systems)

Some modern cron implementations (like systemd timers, Kubernetes CronJobs v1.25+, and cloud schedulers) let you set a timezone per job:

# Kubernetes CronJob with timezone (v1.25+)
spec:
  schedule: "0 9 * * 1-5"
  timeZone: "America/New_York"
# GitHub Actions — always UTC, no timezone override
# Convert manually or use a step to check the time
on:
  schedule:
    - cron: '0 14 * * 1-5'  # 9 AM ET in winter (UTC-5)

Daylight Saving Time Pitfalls

When clocks spring forward, a 2:30 AM job may not fire because 2:30 AM does not exist that night. When clocks fall back, a 1:30 AM job may fire twice. Best practices:

Advanced Cron Patterns and Techniques

Combining Ranges, Lists, and Steps

You can mix special characters within a single field for powerful combinations:

# Every 15 minutes during business hours on weekdays
*/15 9-17 * * 1-5

# At minute 0 and 30, hours 8–12 and 14–18
0,30 8-12,14-18 * * *

# Every 2 hours starting at 1 AM
0 1/2 * * *         # Fires at 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23

Running on Specific Months

# Quarterly — 1st day of Jan, Apr, Jul, Oct at midnight
0 0 1 1,4,7,10 *

# Every weekday in December (holiday prep)
0 9 * 12 1-5

Locking to Prevent Overlap

If a cron job takes longer than its interval, you can end up with overlapping instances that corrupt data or exhaust resources. Use flock to prevent this:

# Only one instance runs at a time
*/5 * * * * /usr/bin/flock -n /tmp/myjob.lock /home/user/scripts/myjob.sh

The -n flag tells flock to exit immediately if the lock is already held, so the second instance simply skips rather than queuing up.

Cron Alternatives Worth Knowing

Best Practices for Production Cron Jobs

After years of collective experience, these practices separate reliable cron setups from fragile ones:

  1. Always use a cron expression builder to verify. Even experienced sysadmins double-check with a tool. Our cron generator shows next run times so you can confirm before deploying.
  2. Log everything. Redirect stdout and stderr to timestamped log files. Rotate logs with logrotate.
  3. Use absolute paths. Never rely on PATH or relative paths in cron commands.
  4. Make scripts idempotent. If a script runs twice by accident, the result should be the same as running once.
  5. Set up alerting. Use MAILTO in crontab, or have your script send a Slack/Discord/PagerDuty alert on failure.
  6. Use lock files. Prevent overlapping executions with flock or a PID file.
  7. Document each job. Add a comment above every crontab entry explaining what it does and who owns it.
  8. Version-control your crontab. Export it periodically with crontab -l > crontab.bak and commit it to your repo.
  9. Prefer UTC for servers. This eliminates DST headaches and makes cross-timezone coordination simpler.
  10. Test in staging first. Never deploy a new cron job directly to production. Test with a short interval (e.g., every minute), verify it works, then set the real schedule.

Frequently Asked Questions

What is a cron expression?

A cron expression is a string of five fields (minute, hour, day of month, month, day of week) that defines a recurring schedule for automated tasks. Each field specifies when a job should run, and the job fires when all fields match the current time.

How do I create a cron expression without memorizing the syntax?

Use a cron expression builder tool. You select your desired schedule from dropdown menus or input fields, and the tool generates the correct cron string. It also shows you the next execution times so you can verify the schedule is right.

What does */5 * * * * mean?

It means "every 5 minutes." The */5 in the minute field tells cron to fire at minutes 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, and 55 of every hour, every day.

Why did my cron job not run?

The most common reasons are: incorrect cron expression syntax, missing environment variables or PATH entries (cron uses a minimal environment), insufficient file permissions, the cron daemon not running, or the script failing silently. Check the cron log (/var/log/syslog on Ubuntu) and ensure your script outputs errors to a log file.

What timezone does cron use?

By default, cron uses the system timezone configured on the server. GitHub Actions always uses UTC. Cloud platforms like AWS and GCP let you specify a timezone. Best practice for production is to run servers in UTC and convert times manually, or use a scheduler that supports explicit timezone configuration.

Can I run a cron job every 30 seconds?

Standard cron's smallest granularity is one minute. To run something every 30 seconds, you can create two cron entries — one that runs at the start of each minute and one delayed by 30 seconds using sleep: * * * * * /path/to/script.sh and * * * * * sleep 30 && /path/to/script.sh. For sub-minute scheduling, consider using systemd timers or a dedicated task queue instead.

What is the difference between cron and crontab?

Cron is the background daemon (service) that reads schedule files and runs jobs at the specified times. Crontab (cron table) is the file that contains the schedule entries, and also the command (crontab -e) used to edit that file. You write cron expressions in your crontab, and the cron daemon executes them.

How do I schedule a cron job in GitHub Actions?

Add a schedule trigger to your workflow YAML file with a cron key. For example, on: schedule: - cron: '0 3 * * *' runs the workflow at 3 AM UTC daily. Remember that GitHub Actions only supports UTC and may delay scheduled runs during high-demand periods.

Conclusion

Cron expressions are deceptively simple — five fields, four special characters, infinite scheduling possibilities. Whether you are setting up a midnight database backup, a weekday-only health check, or a quarterly reporting job, the syntax remains the same. The trick is getting it right the first time.

A cron expression builder takes the guesswork out of the equation. Instead of staring at 0 */4 1-15 * 1-5 and wondering if it does what you think, you get instant visual feedback, plain-English translations, and previews of upcoming execution times. Use our free cron expression generator to build, validate, and copy your next cron schedule in seconds.

For a quick-reference card you can keep open in another tab, check out our cron expression cheat sheet with dozens of copy-paste-ready patterns.

Enjoyed this article?

Get the free Developer Cheatsheet Pack + weekly tips on tools, workflows, and productivity.

Subscribe Free

Try These Tools

Related free tools mentioned in this article

Back to Blog