Cron表达式实战宝典:定时任务从入门到精通
Cron是Unix/Linux系统中用于定时执行任务的工具,Cron表达式是配置定时任务的关键。无论是服务器运维、数据备份还是自动化脚本,掌握Cron表达式都是必备技能。本文将带你从零到精通Cron表达式。
目录
Cron基础概念
什么是Cron?
Cron是一个Linux/Unix的定时任务守护进程(daemon),它会在后台运行,并根据配置的时间表(crontab)自动执行任务。
Cron的应用场景
- 📊 数据备份:每天凌晨自动备份数据库
- 📧 发送邮件:定期发送报表邮件
- 🔄 数据同步:定时同步远程数据
- 🧹 清理任务:定期清理临时文件
- 📈 数据分析:每小时统计业务数据
- 🔔 监控告警:定时检查系统状态
Cron表达式语法
标准Cron表达式(5位)
┌───────────── 分钟 (0 - 59)
│ ┌───────────── 小时 (0 - 23)
│ │ ┌───────────── 日期 (1 - 31)
│ │ │ ┌───────────── 月份 (1 - 12)
│ │ │ │ ┌───────────── 星期 (0 - 6,0代表星期日)
│ │ │ │ │
* * * * *
扩展Cron表达式(6或7位)
┌───────────── 秒(0 - 59)【可选】
│ ┌───────────── 分钟 (0 - 59)
│ │ ┌───────────── 小时 (0 - 23)
│ │ │ ┌───────────── 日期 (1 - 31)
│ │ │ │ ┌───────────── 月份 (1 - 12)
│ │ │ │ │ ┌───────────── 星期 (0 - 6)
│ │ │ │ │ │ ┌───────────── 年份【可选】
│ │ │ │ │ │ │
* * * * * * *
特殊字符说明
| 字符 | 含义 | 示例 |
|---|---|---|
* | 任意值 | * * * * * = 每分钟 |
, | 列表分隔 | 1,15,30 * * * * = 每小时的1、15、30分 |
- | 范围 | 1-5 * * * * = 每小时的1到5分 |
/ | 步长 | */5 * * * * = 每5分钟 |
? | 不指定值(仅日期和星期) | 0 0 ? * 1 = 每周一零点 |
L | 最后(Last) | 0 0 L * * = 每月最后一天 |
W | 工作日(Weekday) | 0 0 15W * * = 最接近15号的工作日 |
# | 第几个星期几 | 0 0 ? * 6#3 = 每月第3个星期五 |
常用Cron表达式
基础时间表达式
# 每分钟执行 * * * * * # 每小时执行(整点) 0 * * * * # 每天执行(午夜) 0 0 * * * # 每周执行(周日午夜) 0 0 * * 0 # 每月执行(1号午夜) 0 0 1 * * # 每年执行(1月1日午夜) 0 0 1 1 *
固定时间执行
# 每天早上8点 0 8 * * * # 每天下午5点30分 30 17 * * * # 每周一早上9点 0 9 * * 1 # 每月15号中午12点 0 12 15 * * # 每年12月31日晚上11点59分 59 23 31 12 *
间隔时间执行
# 每5分钟执行 */5 * * * * # 每15分钟执行 */15 * * * * # 每30分钟执行 */30 * * * * # 每2小时执行 0 */2 * * * # 每6小时执行 0 */6 * * * # 每3天执行(午夜) 0 0 */3 * *
工作日vs周末
# 工作日(周一到周五)早上9点 0 9 * * 1-5 # 周末(周六和周日)早上10点 0 10 * * 6,0 # 工作日每小时 0 * * * 1-5 # 只在工作日的工作时间(9-18点) 0 9-18 * * 1-5
特定时间段
# 早上9点到下午6点,每小时 0 9-18 * * * # 凌晨1点到5点,每2小时 0 1-5/2 * * * # 每个工作日的下午1点到5点,每30分钟 */30 13-17 * * 1-5 # 每周一、三、五的早上8点和晚上8点 0 8,20 * * 1,3,5
高级技巧
组合条件
# 每月1号和15号的早上9点 0 9 1,15 * * # 每周一和周五的早上9点、中午12点、下午6点 0 9,12,18 * * 1,5 # 每季度第一天(1、4、7、10月的1号)早上9点 0 9 1 1,4,7,10 * # 工作日的每个整点(周一到周五) 0 * * * 1-5
使用特殊字符
# 每月最后一天 0 0 L * * # 每月最后一个工作日 0 0 LW * * # 每月最后一个周五 0 0 ? * 5L # 每月第一个周一 0 0 ? * 1#1 # 每月第三个周三 0 0 ? * 3#3 # 最接近15号的工作日 0 0 15W * *
避开特定时间
# 不在整点执行(每小时的第1分钟) 1 * * * * # 避开午夜(凌晨1点) 0 1 * * * # 工作时间外(晚上7点到早上7点) 0 19-7 * * * # 非工作日(周末) 0 0 * * 0,6
不同平台的差异
Linux Crontab
# 查看当前用户的crontab crontab -l # 编辑crontab crontab -e # 删除crontab crontab -r # crontab格式(5位) # 分 时 日 月 周 命令 30 2 * * * /path/to/backup.sh
JavaScript (node-cron)
const cron = require('node-cron'); // 6位表达式(包含秒) // 秒 分 时 日 月 周 cron.schedule('0 */5 * * * *', () => { console.log('每5分钟执行一次'); }); // 支持的特殊字符 cron.schedule('*/10 * * * * *', () => { console.log('每10秒执行'); }); // 任务控制 const task = cron.schedule('* * * * *', () => { console.log('运行中...'); }); task.stop(); // 停止任务 task.start(); // 启动任务
Spring (Java)
import org.springframework.scheduling.annotation.Scheduled; // 6位表达式 @Scheduled(cron = "0 0 2 * * ?") public void dailyBackup() { // 每天凌晨2点执行 } // 7位表达式(包含年份) @Scheduled(cron = "0 0 0 1 1 ? 2024") public void newYearTask() { // 2024年1月1日零点执行 }
Quartz (Java/C#)
// Quartz使用7位表达式 // 秒 分 时 日 月 周 年 "0 0 12 ? * WED" // 每周三中午12点 "0 15 10 * * ? *" // 每天上午10:15 "0 0/5 14 * * ?" // 每天下午2点到2:55,每5分钟
实战案例
案例1:数据库备份
# 每天凌晨3点备份数据库 0 3 * * * /usr/local/bin/backup-database.sh # backup-database.sh脚本内容 #!/bin/bash DATE=$(date +%Y%m%d) BACKUP_DIR="/backups" DB_NAME="myapp" # 创建备份 mysqldump -u root -p$DB_PASSWORD $DB_NAME > $BACKUP_DIR/db_$DATE.sql # 压缩备份文件 gzip $BACKUP_DIR/db_$DATE.sql # 删除30天前的备份 find $BACKUP_DIR -name "db_*.sql.gz" -mtime +30 -delete echo "Database backup completed at $(date)"
案例2:日志清理
# 每周日凌晨4点清理旧日志 0 4 * * 0 /usr/local/bin/cleanup-logs.sh # cleanup-logs.sh #!/bin/bash LOG_DIR="/var/log/myapp" # 删除7天前的日志 find $LOG_DIR -name "*.log" -mtime +7 -delete # 压缩3天前的日志 find $LOG_DIR -name "*.log" -mtime +3 -exec gzip {} \; echo "Log cleanup completed"
案例3:健康检查
# 每5分钟检查服务状态 */5 * * * * /usr/local/bin/health-check.sh # health-check.sh #!/bin/bash SERVICE_URL="https://myapp.com/health" ALERT_EMAIL="admin@example.com" # 检查服务 STATUS=$(curl -s -o /dev/null -w "%{http_code}" $SERVICE_URL) if [ $STATUS -ne 200 ]; then echo "Service is down! Status: $STATUS" | \ mail -s "ALERT: Service Down" $ALERT_EMAIL # 尝试重启服务 systemctl restart myapp fi
案例4:定时报表
# 每天早上9点生成并发送报表 0 9 * * * /usr/local/bin/daily-report.sh # daily-report.sh #!/bin/bash REPORT_DATE=$(date +%Y-%m-%d) REPORT_FILE="/tmp/report_$REPORT_DATE.csv" # 生成报表 mysql -u报表用户 -p密码 -e " SELECT DATE(created_at) as date, COUNT(*) as total_orders, SUM(amount) as total_revenue FROM orders WHERE DATE(created_at) = CURDATE() - INTERVAL 1 DAY GROUP BY DATE(created_at) " mydb > $REPORT_FILE # 发送邮件 echo "Daily Report" | mail -s "报表 $REPORT_DATE" \ -a $REPORT_FILE manager@example.com # 清理临时文件 rm $REPORT_FILE
案例5:缓存预热
# 每天凌晨5点预热缓存 0 5 * * * /usr/local/bin/warm-cache.sh # warm-cache.sh #!/bin/bash API_URL="https://myapp.com/api" # 预热热门页面 curl -s "$API_URL/home" > /dev/null curl -s "$API_URL/products" > /dev/null curl -s "$API_URL/categories" > /dev/null echo "Cache warming completed at $(date)"
常见问题
Q1: Cron任务没有执行怎么办?
检查清单:
# 1. 检查cron服务是否运行 systemctl status cron # 2. 检查crontab语法 crontab -l # 3. 查看cron日志 tail -f /var/log/cron # 或 grep CRON /var/log/syslog # 4. 检查脚本权限 ls -l /path/to/script.sh chmod +x /path/to/script.sh # 5. 使用绝对路径 # ❌ 错误 0 0 * * * backup.sh # ✅ 正确 0 0 * * * /usr/local/bin/backup.sh # 6. 设置环境变量 0 0 * * * source /home/user/.bashrc && /path/to/script.sh
Q2: 如何调试Cron任务?
# 方法1:输出到日志文件 0 0 * * * /path/to/script.sh >> /var/log/myscript.log 2>&1 # 方法2:发送邮件 # cron会自动将输出发送到用户邮箱 0 0 * * * /path/to/script.sh # 方法3:临时增加频率测试 */1 * * * * /path/to/script.sh # 改为每分钟,测试完改回 # 方法4:手动运行脚本 /path/to/script.sh
Q3: Cron表达式生成器
// JavaScript Cron表达式生成器 class CronBuilder { constructor() { this.minute = '*'; this.hour = '*'; this.day = '*'; this.month = '*'; this.weekday = '*'; } everyMinute() { this.minute = '*'; return this; } atMinute(minute) { this.minute = minute.toString(); return this; } everyNMinutes(n) { this.minute = `*/${n}`; return this; } atHour(hour) { this.hour = hour.toString(); return this; } everyNHours(n) { this.hour = `*/${n}`; return this; } onDay(day) { this.day = day.toString(); return this; } onWeekday(weekday) { this.weekday = weekday.toString(); return this; } build() { return `${this.minute} ${this.hour} ${this.day} ${this.month} ${this.weekday}`; } } // 使用示例 const cron = new CronBuilder() .everyNMinutes(30) .atHour(9) .onWeekday(1) // 周一 .build(); console.log(cron); // "*/30 9 * * 1"
Q4: 如何表达"每个工作日的每小时"?
# 方法1:使用星期范围 0 * * * 1-5 # 方法2:使用列表 0 * * * 1,2,3,4,5 # 解释: # 0 - 每小时的第0分钟(整点) # * - 每小时 # * - 每天 # * - 每月 # 1-5 - 周一到周五
Q5: 时区问题如何处理?
# 方法1:在crontab中设置时区 CRON_TZ=Asia/Shanghai 0 9 * * * /path/to/script.sh # 方法2:在脚本中转换时区 #!/bin/bash export TZ='Asia/Shanghai' echo "Current time: $(date)" # 方法3:使用系统时区 timedatectl set-timezone Asia/Shanghai
总结
Cron表达式虽然看起来复杂,但掌握规律后就能轻松应用:
记忆技巧
- 从左到右:分→时→日→月→周
- 星号代表全部:
*表示任意值 - 逗号表示或:
1,15表示1或15 - 横线表示范围:
1-5表示1到5 - 斜杠表示间隔:
*/5表示每5个单位
最佳实践
- ✅ 使用注释说明cron任务的用途
- ✅ 记录输出到日志文件
- ✅ 使用绝对路径
- ✅ 测试脚本权限和执行权限
- ✅ 避开高峰时段执行重任务
相关工具
- ⏰ 在线Cron表达式生成器 - 可视化生成Cron表达式
- 🕐 时间戳转换工具 - 时间格式转换
- 📅 日期计算器 - 计算日期差
关键词: Cron表达式, 定时任务, Linux, Crontab, 任务调度
更新时间: 2026-01-05
相关阅读
其他
TypeScript 类型体操:什么时候值,什么时候在炫技
务实的 TypeScript 高级类型指南 — mapped types、conditional types、template literal types 真正能给你什么,什么时候用,什么时候应该退回到朴素代码。
2026-05-21
其他
Kubernetes 资源 requests / limits 实战:不会把生产搞挂的设法
怎么在生产里实际设 Kubernetes CPU 与内存的 requests/limits — QoS 类、CPU 节流、OOM kill、那些害公司钱的差别,以及好使的模式。
2026-05-18
其他
Vue 3 vs React 2026:下个项目的诚实对比
2026 年 Vue 3 与 React 的诚实对比 — Composition API vs Hooks、性能、生态、TypeScript 表现,以及真正决定选型的标准。
2026-05-15