cron parse schedule cron-expression

精通 Cron 表达式:终极在线 Cron 解析器

使用我们的在线 Cron 解析器轻松解码复杂的 Cron 任务。瞬间获取人类可读的时间表和下次执行时间。

Cron 是什么?从历史说起

Cron 是 Unix 世界中历史最悠久、最经久不衰的工具之一。它由 Ken Thompson 在 1979 年随 Unix V7(第七版 Unix)在贝尔实验室发布。"cron" 这个名字来源于希腊语 chronos(χρόνος),意为"时间"。

最初的 cron 守护进程每分钟唤醒一次,扫描任务列表,执行时间匹配的命令。这种"时间表达式 + 命令"的设计极其简洁,却无比高效,以至于在此后的四十多年里几乎没有发生根本性变化。如今,Linux 发行版普遍使用 Vixie Cron(Paul Vixie,1988 年)、cronie 等改进版本,macOS 则采用 launchd。Cron 的影响还延伸到应用层:Java 的 Quartz Scheduler、Python 的 APScheduler、Node.js 的 node-cron,以及 AWS EventBridge、Google Cloud Scheduler 等云服务,都沿用了 cron 表达式语法。


标准 5 字段 Cron 语法

标准 cron 表达式由 5 个字段组成,以空格分隔:

┌───────── 分钟 (0–59)
│ ┌─────── 小时 (0–23)
│ │ ┌───── 日期 (1–31)
│ │ │ ┌─── 月份 (1–12 或 JAN–DEC)
│ │ │ │ ┌─ 星期 (0–7,0 和 7 均表示周日,或 SUN–SAT)
│ │ │ │ │
* * * * *  命令

各字段详解

字段 允许值 说明
分钟 0–59 任务在每小时第几分钟触发
小时 0–23 24 小时制,0 为午夜
日期 1–31 每月的第几天
月份 1–12 或 JAN–DEC 一年中的月份
星期 0–7 或 SUN–SAT 0 和 7 均代表周日

注意: 当"日期"和"星期"字段同时非 * 时,cron 使用 OR 逻辑——满足任意一个条件就会执行,这常让初学者感到困惑。


扩展 6 字段语法(含秒)

Quartz Scheduler(Java)、Spring Framework@Scheduled 注解以及部分云平台在最前面增加了一个字段:

┌─────────── 秒   (0–59)
│ ┌───────── 分钟 (0–59)
│ │ ┌─────── 小时 (0–23)
│ │ │ ┌───── 日期 (1–31)
│ │ │ │ ┌─── 月份 (1–12)
│ │ │ │ │ ┌─ 星期 (1–7,Quartz 中 1=周日)
│ │ │ │ │ │
0 * * * * ?

注意:Quartz 的星期字段编号不同(1=周日,7=周六),与 Unix cron 的习惯相反,使用时需格外小心。


特殊字符详解

* — 任意值

匹配该字段的所有可能值。* * * * * 表示每分钟执行一次。

, — 值列表

指定多个离散值。0 9,12,18 * * * 表示每天 9:00、12:00、18:00 各执行一次。

- — 范围

指定连续范围。0 9-17 * * 1-5 表示周一至周五每天 9 时到 17 时,每小时整点执行。

/ — 步长

*/n 表示"每隔 n 个单位"。*/15 * * * * 表示每 15 分钟执行一次;0 */2 * * * 表示每隔 2 小时执行一次。也可与范围组合:10-50/10 表示 10、20、30、40、50。

? — 不指定(仅 Quartz/Spring)

用于"日期"或"星期"字段,表示"不关心"。由于同时指定两者会产生歧义,其中一个必须写 ?

L — 最后(仅 Quartz/Spring)

在"日期"字段中表示该月最后一天;在"星期"字段中表示该月最后一个对应星期几。0 0 L * ? 表示每月最后一天午夜执行。0 0 ? * 6L 表示每月最后一个周五午夜执行。

W — 最近工作日(仅 Quartz/Spring)

15W 表示距 15 日最近的工作日。若 15 日是周六,则执行日为 14 日(周五);若是周日,则执行日为 16 日(周一)。

# — 第 N 个星期几(仅 Quartz/Spring)

2#3 表示每月第 3 个周二。格式为 <星期几>#<第几次>0 10 ? * 2#1 表示每月第一个周一 10:00 执行。


特殊时间别名

大多数 cron 实现支持以下便捷别名:

别名 等价表达式 含义
@yearly 0 0 1 1 * 每年 1 月 1 日午夜
@annually 0 0 1 1 * 同 @yearly
@monthly 0 0 1 * * 每月 1 日午夜
@weekly 0 0 * * 0 每周日午夜
@daily 0 0 * * * 每天午夜
@midnight 0 0 * * * 同 @daily
@hourly 0 * * * * 每小时第 0 分钟
@reboot 系统启动后执行一次

常用 Cron 表达式速查表

表达式 含义
* * * * * 每分钟
0 * * * * 每小时整点
*/15 * * * * 每 15 分钟
0 0 * * * 每天午夜
30 2 * * * 每天凌晨 2:30
0 9-17 * * 1-5 工作日每天 9:00–17:00 整点
0 0 * * 0 每周日午夜
0 0 1 * * 每月 1 日午夜
0 0 1 1 * 每年 1 月 1 日午夜
0 6 * * 1-5 工作日每天 6:00
0 */6 * * * 每隔 6 小时

Linux 上的 Crontab 操作

# 编辑当前用户的 crontab
crontab -e

# 查看当前用户的 crontab
crontab -l

# 删除当前用户的 crontab
crontab -r

# 以 root 身份编辑其他用户的 crontab
crontab -u username -e

典型 crontab 示例

# 设置环境变量
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
[email protected]

# 每天凌晨 2:30 执行备份
30 2 * * * /usr/local/bin/backup.sh

# 每周日午夜执行清理,并记录日志
0 0 * * 0 /usr/local/bin/cleanup.sh >> /var/log/cleanup.log 2>&1

# 每 15 分钟执行健康检查
*/15 * * * * /usr/local/bin/health-check.sh

# 指定时区执行(需要 GNU cron 或 cronie 支持)
CRON_TZ=Asia/Shanghai
0 9 * * 1-5 /usr/local/bin/morning-report.sh

系统级 Cron 目录

  • /etc/crontab — 系统级 crontab,每行多一个用户名字段
  • /etc/cron.d/ — 软件包和服务的单独 cron 配置文件
  • /etc/cron.daily//etc/cron.hourly//etc/cron.weekly//etc/cron.monthly/ — 放入这些目录的脚本会由 run-parts 自动按频率执行

macOS 与 Windows 上的调度

macOS:launchd

macOS 已将 launchd 作为推荐的调度机制,通过 .plist 文件定义任务,存放在 ~/Library/LaunchAgents/(用户任务)或 /Library/LaunchDaemons/(系统任务)。不过,cron 在 macOS 上依然可用,许多开发者仍习惯使用它。

Windows:任务计划程序

Windows 使用任务计划程序(Task Scheduler),通过 schtasks 命令或 GUI 操作。WSL(Windows Subsystem for Linux)则提供了完整的 Linux cron 环境。


应用层 Cron 调度器

Node.js — node-cron

const cron = require('node-cron');

// 每天凌晨 2:30 执行,指定时区
cron.schedule('30 2 * * *', async () => {
  await runDailyBackup();
}, {
  timezone: "Asia/Shanghai"
});

Python — APScheduler

from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.triggers.cron import CronTrigger

scheduler = BlockingScheduler()

@scheduler.scheduled_job(CronTrigger.from_crontab('0 9 * * 1-5'))
def morning_job():
    print("工作日早上 9 点,开始执行任务。")

scheduler.start()

云平台与容器调度

AWS EventBridge Scheduler

AWS EventBridge 支持 6 字段 cron 表达式(UTC),日期和星期字段其中一个必须为 ?

cron(0 2 * * ? *)   # 每天 UTC 凌晨 2 点

Google Cloud Scheduler

使用标准 5 字段 Unix cron 语法,支持通过控制台或 API 设置时区。

Kubernetes CronJob

apiVersion: batch/v1
kind: CronJob
metadata:
  name: daily-backup
spec:
  schedule: "0 2 * * *"
  concurrencyPolicy: Forbid
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: backup
            image: backup-image:latest
          restartPolicy: OnFailure

concurrencyPolicy: Forbid 可防止上一次任务尚未完成时新任务重叠启动。


时区处理

Cron 默认使用系统时区,服务器通常设置为 UTC。这是最常见的 bug 来源之一——在 UTC 服务器上设定 0 9 * * * 实际上是 UTC 9 点,换算成北京时间(UTC+8)是下午 17:00。

时区最佳实践:

  1. 在 crontab 中使用 CRON_TZ= 明确指定时区
  2. 云平台(如 GCP Cloud Scheduler、Kubernetes spec.timeZone)使用专用时区字段
  3. 以固定 UTC 时间调度,避免夏令时(DST)切换带来的问题——0 2 * * * 在夏令时变更日可能跳过或重复执行
  4. 在文档和注释中始终注明表达式对应的时区

安全注意事项

Cron 任务通常以较高权限运行,是常见的攻击面,需特别注意:

最小权限原则: 以能完成任务的最低权限用户运行,避免使用 root。

不硬编码凭据: 不要在 crontab 或脚本中直接写入密码、API 密钥等敏感信息。使用权限受限的环境变量文件(chmod 600)或密钥管理服务。

脚本权限管理: 确保 cron 脚本不可被其他用户写入。

chmod 750 /usr/local/bin/backup.sh
chown root:staff /usr/local/bin/backup.sh

监控与告警: 使用 MAILTO= 接收执行输出,并结合 Healthchecks.io 或 Cronitor 等"死亡开关"服务,在任务未按时执行时发出告警。

审计日志: 将所有 cron 任务的执行记录写入日志,便于故障排查和合规审计。


最佳实践

任务幂等性: 确保任务多次执行的结果与执行一次相同,便于从故障中恢复。

使用文件锁防止重叠: 如果任务执行时间可能超过触发间隔,使用 flock

*/5 * * * * flock -n /var/lock/myjob.lock /usr/local/bin/myjob.sh

显式重定向输出: 避免 cron 将输出发送邮件或静默失败:

0 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

部署前验证表达式: 使用 Cron Parser 工具验证表达式是否符合预期,查看未来 5 次执行时间。

版本控制 crontab: 将 crontab 文件纳入 Git,通过 Ansible 或 Puppet 统一部署,避免"配置漂移"。


常见问题解答

Q:Cron 任务不执行,怎么排查?
最常见的原因:①脚本没有执行权限;②脚本依赖当前 Shell 环境变量,而 cron 环境极简;③命令路径问题——cron 不加载你的 Shell 配置,建议所有命令写绝对路径;④cron 守护进程未运行(systemctl status cronsystemctl status crond)。

Q:*/50/5 有什么区别?
在标准 Unix cron 中,*/5 表示从 0 开始每 5 分钟(0、5、10…55)。0/5 是 Quartz/AWS EventBridge 的写法,含义相同。

Q:Cron 能每秒执行一次吗?
标准 cron 的最小粒度是 1 分钟。需要亚分钟级调度,可使用 Quartz、APScheduler,或 systemd timer(OnCalendar=*:*:00/10),也可以让 cron 任务内部循环执行。

Q:如何在每月最后一天执行任务?
标准 cron 没有原生的"最后一天"操作符。常见方案:判断明天是否为 1 日来间接实现。Quartz cron 支持在日期字段直接写 L

Q:0 0 * * 0@weekly 有什么区别?
两者完全等价,都表示每周日午夜执行。@weekly 只是大多数现代 cron 实现提供的助记别名。

Q:在终端运行正常的脚本,为什么在 cron 中失败?
Cron 运行环境极简(通常只有 HOMELOGNAMEPATH=/usr/bin:/binSHELL=/bin/sh),不加载 .bashrc.profile。建议脚本首行写 #!/bin/bash,添加 set -e 在出错时退出,使用绝对路径,并将 stdout/stderr 全部重定向到日志文件。


总结

Cron 自 1979 年诞生以来,一直是 Unix 自动化调度的基石,并在云时代焕发了新的生命力。无论是管理单台 Linux 服务器、编排 Kubernetes 工作负载,还是配置云端事件触发,深入理解 cron 表达式都能帮助你避免大量调试工作,防止因调度失误带来的生产故障。

核心要点:

  • 5 字段标准语法覆盖绝大多数场景
  • / 表示步长,, 表示列表,- 表示范围
  • 服务器优先使用 UTC,或明确指定 CRON_TZ
  • 遵守最小权限、不硬编码凭据、做好监控等安全原则
  • 上线前用解析工具验证表达式,避免低级错误

概述

Cron 任务是现代自动化的核心,但其语法即便对于经验丰富的系统管理员来说也可能令人生畏。我们的在线 Cron 解析器旨在消除调度中的盲目性。通过将晦涩的 Cron 表达式翻译成清晰、易懂的语言,该工具可确保您的计划任务完全按照您的意图运行。无论您是在管理备份、清理脚本还是自动化电子邮件,准确性都至关重要。

核心功能

  • 实时翻译: 立即以纯文本(或您选择的语言)查看 Cron 表达式的含义。
  • 下次运行时间: 查看未来 5 次或更多次计划执行时间的列表,以验证您的逻辑。
  • 支持所有字段: 处理标准 Cron 格式,包括秒(6 字段)和年(7 字段)变体。
  • 语法高亮: 视觉提示可帮助您识别分钟、小时、日、月和星期。

使用指南

  1. 输入: 在主字段中粘贴或键入您的 Cron 表达式。
  2. 观察: 易于理解的翻译会随着您的键入自动更新。
  3. 验证: 检查“下次执行时间”列表以确保它符合您的要求。
  4. 复制: 如果您从头开始,请使用提供的示例。

常见应用场景

  • 服务器维护: 调度每晚数据库备份或日志轮转。
  • Web 开发: 在 Laravel 或 Django 等框架中设置循环后台任务。
  • DevOps: 配置 CI/CD 流水线和自动化健康检查。
  • 个人生产力: 管理本地计算机上的循环提醒或脚本执行。

技术背后的原理

Cron 表达式由 5 到 7 个由空格分隔的字段组成。每个字段代表一个时间单位:分钟、小时、月中某天、月份和周中某天。我们的解析器使用强大的逻辑引擎,可以处理特殊字符,如 *(任意)、,(列表)、-(范围)、/(增量)和 L(最后)。它通过考虑闰年和月份长度来准确计算下一次发生的时间。

常见问题解答

  • 它支持秒吗? 是的,它支持包含秒的 6 字段 Cron 表达式。
  • 它能处理像 @daily 这样的非标准别名吗? 是的,支持常见的别名。
  • 它支持时区吗? 默认情况下,计算基于 UTC,但您可以相应地调整您的视角。

使用限制

  • 实现差异: 不同的系统(例如 Quartz、AWS、Jenkins)在 Cron 语法上有细微差别;请始终在您的特定平台上进行验证。
  • 边缘情况: “每月最后一天”(L)和“最近的工作日”(W)的行为可能因操作系统而异。