⏰ Cron 是什么?从 0 到精通这门“时间语言”
「每天凌晨 2 点自动清理数据库」「每 15 分钟同步缓存」「每周一早上 8 点发送报告」——这些自动化任务背后都有一个低调而强大的角色:Cron。
一、Cron 是什么?
Cron 是一种用于描述“任务在什么时间执行”的表达式语言。它本身不执行任务,只负责定义 何时 触发,由调度器(Scheduler)在匹配的时间点调用你的代码。
你可以把它理解为“时间的 DSL(领域特定语言)”。
二、为什么要懂 Cron?
- 定时清理、数据归档、报表生成、缓存刷新、外部同步等后端任务都依赖它。
- 现代框架(NestJS、Spring、Django 等)与云平台(Kubernetes、Serverless)普遍支持 Cron。
在 NestJS 中只需一行即可创建定时任务:
import { Cron } from '@nestjs/schedule';
@Cron('0 0 2 * * *', { timeZone: 'UTC' })
handleCron() {
console.log('每天凌晨 2 点执行任务');
}
三、Cron 表达式的两类格式
1) 标准 Unix(5 字段)
分 时 日 月 周
示例:
0 2 * * *
含义:每天 02 执行。
2) 扩展格式(6 字段,NestJS 使用)
秒 分 时 日 月 周
示例:
0 0 2 * * *
含义:每天 02:00 执行。
✅ NestJS 必须使用 6 字段;
❌ 用 5 字段会被错位解析,导致时间混乱。
四、字段结构图解(6 字段)
┌──────────── 秒 (0–59)
│ ┌────────── 分 (0–59)
│ │ ┌──────── 时 (0–23)
│ │ │ ┌────── 日 (1–31)
│ │ │ │ ┌──── 月 (1–12)
│ │ │ │ │ ┌── 周 (0–7,0/7=周日)
│ │ │ │ │ │
0 0 2 * * * → 每天 02:00:00 执行
五、语法速查
| 符号 | 含义 | 示例 |
|---|---|---|
* |
任意值 | * * * * * * → 每秒 |
, |
多个值 | 0 0 8,20 * * * → 8 点和 20 点 |
- |
范围 | 0 0 9-17 * * 1-5 → 工作日 9–17 点整点 |
/ |
步长 | 0 */15 * * * * → 每 15 分钟 |
六、常见表达式(6 字段)
| 表达式 | 含义 | 执行时间 |
|---|---|---|
0 0 2 * * * |
每天凌晨 2 点 | 02:00 |
0 30 3 * * * |
每天 3 | 03:30 |
0 0 */6 * * * |
每 6 小时 | 00、06、12、18 |
0 0 8 * * 1-5 |
工作日早 8 点 | 周一至周五 08:00 |
0 0 0 1 1 * |
每年元旦 | 01-01 00:00 |
0 */15 * * * * |
每 15 分钟 | 00、15、30、45 分 |
七、NestJS 最佳实践
1) 环境变量(带引号更安全)
# .env.production
CLEANUP_ENABLED=true
CLEANUP_CRON="0 0 2 * * *"
CLEANUP_TIMEZONE=UTC
2) 配置类
export class RateLimitConfig {
static readonly CLEANUP = {
ENABLED: process.env.CLEANUP_ENABLED === 'true',
CRON: process.env.CLEANUP_CRON || '0 0 2 * * *',
TIMEZONE: process.env.CLEANUP_TIMEZONE || 'UTC',
};
}
3) Service 中注册任务
@Cron(RateLimitConfig.CLEANUP.CRON, {
name: 'cleanup-job',
timeZone: RateLimitConfig.CLEANUP.TIMEZONE,
})
async cleanup() {
if (!RateLimitConfig.CLEANUP.ENABLED) return;
// 你的清理逻辑...
}
八、常见误区对比
| 错误写法 | 问题 | 正确写法 |
|---|---|---|
0 2 * * * |
5 字段导致错位解析 | "0 0 2 * * *" |
0 0 2 * * *(无引号) |
shell 可能拆分空格 | "0 0 2 * * *" |
| 未指定时区 | 不同服务器表现不一致 | timeZone: 'UTC' 或 'Asia/Shanghai' |
九、时区(TimeZone)
- Cron 默认用系统时区;云/容器环境多为 UTC。
- 建议:开发用
Asia/Shanghai方便本地验证;生产统一用UTC。
@Cron('0 0 2 * * *', { timeZone: 'Asia/Shanghai' })
| 时区 | 说明 |
|---|---|
UTC |
协调世界时(生产推荐) |
Asia/Shanghai |
北京时间(UTC+8) |
America/New_York |
美东时间 |
Europe/London |
伦敦时间 |
十、验证与调试
本地验证
npm i cron-parser
import * as parser from 'cron-parser';
const it = parser.parseExpression('0 0 2 * * *');
console.log('Next 5 runs:');
for (let i = 0; i < 5; i++) console.log(it.next().toString());
在线工具
十一、时间轴示意
时间线(示例:0 0 2 * * *):
00:00 ──────────────┬─────────────┬─────────────┬─────────────
↑
└─ 02:00:00(每天)
十二、它属于哪个类别?
归属领域: 任务调度(Job Scheduling)/ 系统自动化调度。
技术栈层级: 后端基础设施能力,介于应用层与系统运维之间。
与数据库关系: 常用于触发数据库的备份/清理/归档,但它本身不是数据库技术。
知识图谱定位:
软件工程
├─ 后端开发
│ ├─ Web 框架(NestJS、Spring)
│ ├─ 任务队列(BullMQ、Celery)
│ └─ 定时任务(Cron / @nestjs/schedule)✅
├─ 系统运维
│ ├─ 进程管理(pm2、systemd)
│ └─ Cron 守护进程(crond)✅
└─ 数据库管理
└─ 借助 Cron 触发备份/清理/归档(间接)⚙️
十三、总结
- Cron 是“时间的语言”,只定义“何时执行”,不负责“执行什么”。
- NestJS 使用 6 字段(秒 分 时 日 月 周),务必与 5 字段区分。
- 时区要明确,生产推荐统一使用
UTC。 - 写完要验证(
cron-parser/ 在线工具)。
掌握 Cron,你就掌握了让系统按时自驱的能力。愿每个自动任务都稳准达!
延伸阅读
- Node-Cron:https://github.com/node-cron/node-cron
- NestJS Task Scheduling:https://docs.nestjs.com/techniques/task-scheduling
- Crontab Guru(5 字段):https://crontab.guru/
- CronHub(6 字段):https://crontab.cronhub.io/
订阅 FreeMac
每周精选:Mac 高效技巧、免费替代付费软件、开发者工具推荐。用对你的 MacBook,省钱 + 提效。