凌晨数据库备份
运维值班的凌晨 2 点,需要写一条 cron 让服务器在每天凌晨 3 点 15 分执行数据库全量备份。手动写 `15 3 * * *` 总担心写反了分钟和小时的位置,或是漏掉了星期字段导致周末也跑。把表达式贴进工具,右侧立即给出人类可读的「每天 03:15」和下一次执行时间,确认无误后再部署到 crontab,不用再靠肉眼反复核对。
凌晨两点,运维盯着“0 0 2 * * ?”这个表达式,想确认它到底会不会在明天凌晨两点跑。全宝工具 Cron 表达式校验器,输入表达式即可实时校验合法性,逐段中文解释每个字段含义,并列出未来 N 次执行时间。所有解析在浏览器本地完成,表达式不上传服务器,无需担心敏感任务泄露。
运维值班的凌晨 2 点,需要写一条 cron 让服务器在每天凌晨 3 点 15 分执行数据库全量备份。手动写 `15 3 * * *` 总担心写反了分钟和小时的位置,或是漏掉了星期字段导致周末也跑。把表达式贴进工具,右侧立即给出人类可读的「每天 03:15」和下一次执行时间,确认无误后再部署到 crontab,不用再靠肉眼反复核对。
应用日志每天增长 2GB,磁盘告警阈值是 85%。准备写一条 cron 在每周日凌晨 4 点删除 7 天前的 .log 文件。但 7 天前跨了月份边界,用 `0 4 * * 0` 只能保证周日执行,无法判断文件年龄。工具解析后发现这条表达式只在周日触发,于是改成 `0 4 * * 0` 配合脚本内的 find 命令,工具验证了「每周日 04:00」的语义,确保不会在周一凌晨误删。
团队有台服务器在 UTC 时区,但业务需要在北京时间每天上午 9 点推送报表。手动把北京时间换算成 UTC 时间(凌晨 1 点)后写 `0 1 * * *`,工具解释为「每天 01:00」,但不确定是否包含夏令时影响。把表达式输入后,工具明确列出未来 5 次执行时间,全部落在凌晨 1 点整,排除夏令时偏移风险,直接复制到服务器。
财务系统需要在每个月最后一天上午 10 点自动发送工资邮件。但「最后一天」在 cron 标准语法里没有直接表达,常见写法 `0 10 28-31 * *` 会在 2 月 28 日、30 日等非法日期也触发。把这条表达式贴进工具,工具列出 2025 年 2 月的执行日期,发现 2 月 28 日被触发,但 2 月 30 日不存在所以跳过,确认了这种「范围+跳过」的实际行为,才放心使用。
技术团队每两周的周三下午 3 点开复盘会,需要一条 cron 在会议前 15 分钟发钉钉提醒。尝试 `45 14 * * 3` 只能做到每周三,无法隔周执行。工具解析后发现该表达式是「每周三 14:45」,于是改为 `45 14 1-7,15-21 * 3`,工具验证出该表达式在每月 1-7 日和 15-21 日的周三触发,正好覆盖双周节奏,且不会在 8-14 日或 22-月末的周三误发。
| 维度 | 本工具 | 竞品 A (crontab.guru) | 传统方法 (man crontab) |
|---|---|---|---|
| 隐私 | 表达式解析在浏览器本地完成,不上传服务器 | 解析在服务端完成,表达式会发送至其服务器 | 完全离线,无网络依赖 |
| 速度 | 输入后即时反馈,无网络延迟 | 依赖网络,响应速度受服务器负载影响 | 需手动执行 crontab 命令或查阅文档,速度最慢 |
| 离线可用 | 支持离线使用,页面加载后断网仍可解析 | 必须联网,断网无法使用 | 完全离线 |
| 学习成本 | 提供中文解释与下次执行时间,零门槛 | 英文界面,需理解英文术语 | 需记忆 cron 语法与 man 手册,学习成本最高 |
| 下次执行时间 | 直接列出未来 N 次执行的具体日期时间 | 仅显示下一次执行时间 | 需手动计算或编写脚本推算 |
| 表达式长度 | 支持标准 5 段与 6 段(含秒)表达式 | 仅支持标准 5 段 | 支持任意段数,但需手动解析 |
| 输入 | 输出 | 说明 |
|---|---|---|
| 0 0 * * * | 每天 00:00 执行一次 | 常规:最基础的每日定时任务,验证工具能否正确解析标准 5 段格式并输出中文描述 |
| */5 9-17 * * 1-5 | 周一至周五 09:00-17:00 每 5 分钟执行一次 | 常规:典型工作日轮询场景,验证步长(*/5)、范围(9-17)、星期(1-5)的组合解析 |
| 0 0 1 1 * | 每年 1 月 1 日 00:00 执行一次 | 边界:年任务,验证月份和日期同时指定时的逻辑,以及跨年边界(如 2 月 29 日) |
| 0 0 29 2 * | 每年 2 月 29 日 00:00 执行一次(仅闰年有效) | 边界:闰年特有日期,验证工具是否提示非闰年不触发,暴露日期合法性校验 |
| 0 0 * * 0 | 每周日 00:00 执行一次 | 易错:星期字段 0 和 7 都表示周日,验证工具是否统一处理(部分实现只认 7) |
| 0 0 1 * 7 | 每周日 00:00 执行一次(部分实现视为周日,部分视为周六) | 易错:7 在星期字段中含义有歧义(周日 vs 周六),验证工具是否明确标注或给出警告 |
| 0 0 1 1 0 | 每年 1 月 1 日且为周日时 00:00 执行一次 | 易错:日期和星期同时指定时,逻辑为 AND(同时满足)而非 OR,验证工具是否正确解释 |
1.星期字段同时用数字和英文缩写,导致冲突
0 0 * * 1,Mon0 0 * * 1Cron 星期字段数字(0=周日)和英文缩写(MON)是同一语义的不同表示,混用会导致解析器重复匹配或报错,标准实现只接受一种表示。
2.月份字段用 0 代替 1,导致表达式无效
0 0 1 0 *0 0 1 1 *Cron 月份字段范围是 1-12(或 JAN-DEC),0 不在合法区间内,多数解析器直接拒绝执行,不会自动修正为 1 月。
3.步长值超出字段范围,表达式静默失效
*/15 * * * **/15 * * * *步长值本身合法,但若步长与字段最大值不整除(如分钟 /15 在 0-59 内正常),问题出在用户误以为步长可跨天——实际上步长只在当前字段范围内循环。
4.星期字段用 7 表示周日,但标准只认 0
0 0 * * 70 0 * * 0多数 Unix cron 实现中星期天用 0 表示,7 不被识别或视为非法值,部分解析器会报错而非自动转换。
5.在分钟字段使用超过 59 的数值
60 0 * * *0 0 * * *分钟字段合法范围是 0-59,60 超出边界,大多数解析器直接拒绝执行,不会自动截断或取模。
6.误以为 L 表示最后一天,但标准 cron 无此语法
0 0 L * *0 0 28-31 * *L 是 Quartz 调度器的扩展语法,标准 Unix cron 不支持。在标准 cron 中 L 会被当作普通字符导致表达式无效。
7.逗号列表包含重复值,造成冗余匹配
0 0 * * 1,1,20 0 * * 1,2逗号列表中的重复值不会带来额外触发,但会增加解析开销,某些实现可能产生意外行为(如触发次数翻倍)。
8.在星期字段使用 * 和具体值组合,语义混乱
0 0 * * 1-5,60 0 * * 1-5星期字段的 * 已表示所有天,再追加具体值会导致逻辑重复或冲突,部分解析器会忽略 * 或报错。
next_time = min{ t ∈ T | t > now ∧ match(t, cron_expr) }
now当前时间戳,精确到秒cron_expr6/7 段 Cron 表达式字符串T所有可能的时间点集合match(t, expr)判断时间 t 是否满足表达式当前时间 2025-04-10 14:30:00,表达式 '30 15 * * 1-5'(周一到周五 15:30)。从 now 向后逐秒扫描:第一个满足的时间是 2025-04-10 15:30:00(当天周四),即 next_time = 2025-04-10 15:30:00。
6 种主流语言实现,复制即用:
from croniter import croniter
from datetime import datetime
# 校验并获取接下来 5 次执行时间
cron_expr = "*/5 * * * *" # 每 5 分钟
base = datetime.now()
cron = croniter(cron_expr, base)
for i in range(5):
print(cron.get_next(datetime)) # 下次执行时间const parser = require('cron-parser');
const interval = parser.parseExpression('0 9 * * 1-5'); // 工作日 9:00
for (let i = 0; i < 5; i++) {
console.log(interval.next().toISOString()); // 下次执行时间
}package main
import (
"fmt"
"github.com/robfig/cron/v3"
"time"
)
func main() {
expr := "0 0 1 * *" // 每月 1 日 0 点
schedule, _ := cron.ParseStandard(expr)
now := time.Now()
for i := 0; i < 5; i++ {
next := schedule.Next(now)
fmt.Println(next)
now = next
}
}#!/bin/bash
# 使用 crontab 内置语法校验(不实际安装)
# 仅校验格式,不计算下次执行
cron_expr="30 4 * * 1"
echo "$cron_expr" | crontab -i - 2>&1 || echo "格式无效"import com.cronutils.model.Cron;
import com.cronutils.model.definition.CronDefinitionBuilder;
import com.cronutils.model.time.ExecutionTime;
import com.cronutils.parser.CronParser;
import java.time.ZonedDateTime;
public class CronNext {
public static void main(String[] args) {
String expr = "0 0/30 * * * ?"; // 每 30 分钟
CronParser parser = new CronParser(CronDefinitionBuilder.defineCron()
.withSeconds().withMinutes().withHours().withDoM().withMonth().withDoW().instance());
Cron cron = parser.parse(expr);
ExecutionTime exec = ExecutionTime.forCron(cron);
ZonedDateTime now = ZonedDateTime.now();
for (int i = 0; i < 5; i++) {
now = exec.nextExecution(now).get();
System.out.println(now);
}
}
}<?php
require 'vendor/autoload.php';
use Cron\CronExpression;
$cron = CronExpression::factory('0 0 * * 0'); // 每周日 0 点
$nextRun = $cron->getNextRunDate('now', 0, true); // 下次执行
for ($i = 0; $i < 5; $i++) {
echo $nextRun->format('Y-m-d H:i:s') . "\n";
$nextRun = $cron->getNextRunDate($nextRun, 1, true);
}最常见的原因是格式错误,比如用了中文逗号或空格数不对。标准 cron 是 5 段(分 时 日 月 周),6 段(加秒)或 7 段(加年)也支持,但段数必须严格匹配。本工具在输入框下方会实时提示当前段数和格式状态,如果完全没反应,先检查是否混入了全角符号或多余空格。另外,浏览器控制台如果有报错,可能是脚本加载问题,刷新页面重试即可。
cron 表达式的日期字段(第 3 位)是「几号」,不是「几天后」。'0 0 1 * *' 意思是「每月 1 号 0 点 0 分」,工具会从当前时间往后找最近一次满足条件的时刻。如果今天不是 1 号,它自然跳到下个月 1 号。如果你想要「每隔 1 天执行一次」,应该用 '0 0 */1 * *' 或 '0 0 * * *'(每天),而不是用 '1' 这个数字。
本工具遵循标准的 POSIX cron 规则,与 Linux crontab 的 5 段格式完全兼容。但它额外支持 6 段(秒)和 7 段(年)的非标准扩展,这些在原生 Linux cron 中不识别。另外,工具在解释时会把星期字段(第 5 位)的 0 和 7 都视为周日,这与多数 Linux 实现一致。如果你的表达式在服务器上跑正常但工具报错,大概率是段数不一致——检查你系统里用的是否是 5 段标准版。
当第 3 位(日)和第 5 位(周)同时指定非 * 值时,标准 cron 行为是「两个条件满足任意一个就执行」,即「每月 1 号或者每周五都执行」。但某些实现(如 Quartz)会要求两者同时满足。本工具默认采用标准 UNIX 逻辑(或关系),并在表达式解释结果里明确标出「匹配条件:日 OR 周」。如果你需要严格同时满足,建议只用其中一个字段,另一个写 *。
检查是否跨了夏令时切换日。cron 基于系统时钟,如果时区有夏令时,每年 3 月和 11 月某天会「少一小时」或「多一小时」。本工具在计算下次执行时使用的是用户浏览器本地时区,如果浏览器自动应用了夏令时,结果就会「跳」或「重复」一小时。解决方案:在工具结果区查看时区标注,确认是否启用了夏令时调整。如果任务必须固定 UTC 时间,建议用 0 时区(UTC)的表达式。
是的,完全在浏览器本地计算,不发送任何网络请求。表达式的校验、解释和下次 N 次执行时间推算全部由前端 JavaScript 完成。可以断网测试——关闭 Wi-Fi 后刷新页面,工具仍然可以正常使用。这意味着即使表达式包含敏感信息(比如任务名中含业务关键词),也不会离开本机。所有计算结果都只存在当前页面内存中,刷新即消失。
标准 cron 第一段是分钟,不是秒。'*/5 * * * *' 表示「每 5 分钟」,具体是 0、5、10……55 分执行,不是每 5 秒。如果你需要每 5 秒执行一次,必须用 6 段格式,例如 '*/5 * * * * *'(第一段是秒)。本工具会根据你输入的段数自动识别格式,并在解释结果开头写明「共 X 段,已按 XX 格式解析」。如果误用了 5 段写秒,工具会直接报段数错误。
本工具支持标准的数字、星号、逗号、连字符、斜杠(枚举、范围、步长)以及问号(?)用于周/日字段的互斥占位。但 L(最后一天/最后一个周几)、W(最近工作日)、#(第几个周几)属于 Quartz 调度器的扩展语法,非 POSIX 标准,本工具目前不支持。如果你的调度系统是 Quartz(如 Java 项目),建议改用其他专为 Quartz 设计的 cron 工具。
隐私保证所有计算与处理均在你的浏览器本地完成,输入数据不会上传服务器,也不会保存或共享。