K
ken
首页文章🕐 时间转换📋 JSON 工具🖼️ Base64 图片🔑 密码生成 Cron 表达式🔤 命名转换📱 二维码生成#️⃣ 哈希计算🔡 编码转换🔍 正则表达式⚙️ 配置文件格式转化🔐 加解密⚖️ BMI 计算🎲 随机数据🗜️ 图片工具🌍 世界时钟🏛️ 罗马数字🔢 数字转中文💰 贷款计算
DevOps

Cron Expression Guide: Syntax, Examples and Common Schedules

2026-04-25·6 分钟阅读

What is a Cron Expression?

A cron expression is a string that defines when a scheduled task should run. If you have ever needed to run a script "every day at 3 AM" or "every Monday at 9:30 AM", cron is the tool you reach for.

Cron has been around since the 1970s. It has not changed much because it does not need to — the 5-field expression system is compact, precise, and universally supported across Unix-like systems.

The 5-Field Syntax

A cron expression has 5 fields separated by spaces:

code双击代码复制
┬    ┬    ┬    ┬    ┬
│    │    │    │    └─  Day of Week (0-7, 0 and 7 = Sunday)
│    │    │    └──────  Month (1-12)
│    │    └────────────  Day of Month (1-31)
│    └─────────────────  Hour (0-23)
└──────────────────────  Minute (0-59)

Each field supports:

  • Wildcard (*): Matches every value. `*` in the hour field means "every hour".
  • Range (-): `9-17` means "from 9 AM to 5 PM inclusive".
  • Step (/): `*/15` in minutes means "every 15 minutes".
  • List (,): `1,3,5` means "Monday, Wednesday, Friday".
  • Combined: `*/10 9-17 * * 1-5` means "every 10 minutes, between 9 AM and 5 PM, Monday through Friday".
  • Common Cron Schedules

    Here are patterns I use regularly:

    code双击代码复制
    # Every day at 3:00 AM (backup scripts, log rotation)
    0 3 * * *
    
    # Every hour (health checks, cache warming)
    0 * * * *
    
    # Every 5 minutes (high-frequency monitoring)
    */5 * * * *
    
    # Every Monday at 9:00 AM (weekly reports)
    0 9 * * 1
    
    # First day of every month at midnight (monthly cleanup)
    0 0 1 * *
    
    # Every weekday at 6:00 PM (end-of-day tasks)
    0 18 * * 1-5

    Setting Up a Cron Job

    Cron jobs are managed through the crontab file. Each user has their own.

    bash双击代码复制
    # Edit your crontab
    crontab -e
    
    # List your current cron jobs
    crontab -l
    
    # Remove all cron jobs
    crontab -r

    The crontab format adds six optional environment variable fields before the schedule:

    bash双击代码复制
    # Example crontab entry
    SHELL=/bin/bash
    PATH=/usr/local/bin:/usr/bin:/bin
    
    # Run backup script every day at 2:30 AM
    30 2 * * * /home/user/scripts/backup.sh >> /var/log/backup.log 2>&1
    
    # Clean temp files every hour
    0 * * * * find /tmp -type f -mtime +1 -delete

    Special Syntax: @reboot and Friends

    Some cron implementations support @-strings for common schedules:

    bash双击代码复制
    @reboot     # Run once at startup
    @daily      # Run once a day (0 0 * * *)
    @weekly     # Run once a week (0 0 * * 0)
    @monthly    # Run once a month (0 0 1 * *)
    @yearly     # Run once a year (0 0 1 1 *)
    @hourly     # Run once an hour (0 * * * *)

    @reboot is particularly useful for starting services or daemons when a server restarts unexpectedly.

    Cron in Docker Containers

    Cron does not run inside Docker containers by default. You either install cron in the container or use the host cron to trigger docker exec:

    bash双击代码复制
    # Host-side cron to run a container task
    0 3 * * * docker exec my-container /usr/local/bin/backup

    Alternatively, use a dedicated cron container image that bundles cron:

    dockerfile双击代码复制
    FROM alpine:latest
    RUN apk add --no-cache dcron
    COPY crontab /var/spool/cron/crontabs/root
    CMD ["crond", "-f", "-l", "2"]

    Logging and Debugging

    Cron has a reputation for being hard to debug. A job fails silently and you only find out weeks later.

    Two rules I follow:

    1. Always redirect output to a log file. If you do not, cron sends output as email (which is often not configured).

    bash双击代码复制
    # Bad: output disappears
    30 2 * * * /home/user/scripts/backup.sh
    
    # Good: output is logged
    30 2 * * * /home/user/scripts/backup.sh >> /var/log/backup.log 2>&1

    2. Use absolute paths. Cron runs with a minimal environment. Your script may work in your terminal and fail in cron because $PATH is different.

    bash双击代码复制
    # Bad: may fail in cron
    30 2 * * * python3 script.py
    
    # Good: explicit paths
    30 2 * * * /usr/bin/python3 /home/user/scripts/script.py

    A Real Mistake

    Last year I set up a cron job to renew an SSL certificate every 2 months. I wrote:

    bash双击代码复制
    0 0 1 */2 * /usr/bin/certbot renew

    I thought "*/2" in the month field means "every 2 months". It does. But the day-of-month field is "1", so the job ran on the 1st of every 2nd month. The certificate expired on March 15th and the next run was April 1st. My site went down for two weeks while I was on vacation.

    The fix: use a monitoring service to check certificate expiry, and set up a daily cron for cert renewal that only runs if renewal is needed (which is what certbot renew does by default — it checks before renewing).

    Wrap Up

    Cron is one of those Unix tools that looks simple on the surface but has enough edge cases to fill a book. Use absolute paths, log everything, and never assume your cron expression means what you think it does without testing it first with a cron expression parser.