cron 触发器详解

📅 2026/8/6 21:44:53
cron 触发器详解
一、什么是 Cron 触发器Cron 源自 Linux/Unix 的 crontab是一套基于时间表达式的定时规则。在 APScheduler 中CronTriggercron触发器是生产环境使用频率最高的触发器适合实现按年、月、日、周、时、分、秒定点周期性执行任务。区分interval每隔多久执行一次间隔cron到哪个时间点才执行定点很多同学混淆两者比如“每2小时跑一次”用interval“每天早上8点半、晚上21点跑”这种固定时间点优先选cron。APScheduler 的 cron 比 Linux 原生 crontab 更强大支持秒级粒度Linux crontab最小粒度是分钟。二、CronTrigger 参数总览APScheduler cron 的全部参数顺序秒、分、时、日、月、星期、年年为可选参数含义取值范围second秒0‑59minute分钟0‑59hour小时0‑23day每月几号1‑31month月份1‑12day_of_week星期0‑60周日也支持简写mon/tue/wed/thu/fri/sat/sunyear年份可选如2026⚠️重要坑Linux crontab没有秒字段APScheduler多了second不要直接照搬linux cron表达式。day和day_of_week是或关系不是且关系两者条件满足其一就触发新手极易踩坑。三、通配符语法详解cron所有字段都支持下面5种语法这是写定时规则的基础符号说明示例*通配代表该字段所有值都匹配hour*→ 每小时,指定多个值逗号分隔hour8,10,14→ 8、10、14点-区间连续范围day_of_week1‑5→ 周一到周五/步长起始/间隔minute0/10→ 从0分开始每10分钟执行一次?仅部分cron实现支持APScheduler不使用不要写-语法示例minute0,15,30,45每小时的0、15、30、45分执行hour9‑189点至18点包含9和18second0/5从0秒开始每5秒执行一次四、APScheduler 基础代码模板fromdatetimeimportdatetimefromapscheduler.schedulers.blockingimportBlockingSchedulerdeftask():print(fcron任务执行当前时间{datetime.now()})schedulerBlockingScheduler()scheduler.add_job(functask,triggercron,second0,minute0,hour8,12,18,iddemo_cron_job)scheduler.start()等价于直接构造CronTrigger对象fromapscheduler.triggers.cronimportCronTrigger triggerCronTrigger(hour8,12,18,minute0,second0)scheduler.add_job(task,triggertrigger,iddemo_cron_job)五、业务常用实战示例全部为 APScheduler 写法带秒字段1. 每天凌晨0点整执行scheduler.add_job(task,cron,hour0,minute0,second0)2. 每周一到周五早上9点30分执行scheduler.add_job(task,cron,day_of_weekmon‑fri,hour9,minute30,second0)3. 每天 8、10、12、15、17、22点整点爬虫多时段采集scheduler.add_job(task,cron,hour8,10,12,15,17,22,minute0,second0)4. 工作时间内每30分钟执行一次9‑18点0分、30分scheduler.add_job(task,cron,hour9‑18,minute0,30,second0)5. 每月1号凌晨2点执行月度统计、数据归档scheduler.add_job(task,cron,day1,hour2,minute0,second0)6. 每10秒执行一次步长写法scheduler.add_job(task,cron,second0/10)7. 每年5‑10月每周六下午14点执行scheduler.add_job(task,cron,month5‑10,day_of_weeksat,hour14,minute0,second0)六、高频坑点解析坑1day 和 day_of_week 是或关系最容易出错示例需求每个月1号并且是周一才执行❌错误写法满足“是1号”或者“是周一”就跑不是同时满足# 错误或逻辑scheduler.add_job(task,cron,day1,day_of_week1,hour8,minute0,second0)APScheduler cron没有原生“且”的语法。解决方案任务照常触发函数内部做业务判断过滤。importdatetimedeftask():nowdatetime.datetime.now()# 必须同时满足每月1号 并且 周一ifnow.day1andnow.weekday()0:print(满足条件执行业务逻辑)else:print(不满足条件直接跳过)坑2照搬Linux crontab表达式忘记秒字段Linux crontab0 8 * * *代表每天8点。Linux顺序分 时 日 月 星期。APScheduler的cron第一位是秒如果直接复制会错位Linux0 8 * * *→ (分0时8)APScheduler想要每天8点整second0, minute0, hour8坑3夏令时导致任务漏跑/重复执行时区切换夏令时会出现时钟跳变导致任务漏执行或者执行两次。解决初始化调度器时指定时区建议使用东八区Asia/Shanghai。schedulerBlockingScheduler(timezoneAsia/Shanghai)坑4任务执行时长超过调度周期出现并发跑多个实例比如任务需要跑10分钟cron配置每5分钟触发一次上一轮还没结束下一轮又启动造成重复跑、数据错乱。解决配置max_instances限制最大并发实例数scheduler.add_job(functask,triggercron,hour8‑18,minute0/5,second0,max_instances1# 同一时刻最多只允许1个实例运行防止重跑)max_instances1上一个任务没跑完新触发会直接丢弃本次调度不会并发。坑5程序启动不会立刻执行cron触发器只会等待下一个符合条件的时间点程序启动不会马上跑。需要启动即执行一次增加next_run_time参数fromdatetimeimportdatetime scheduler.add_job(functask,triggercron,hour8,12,18,minute0,second0,next_run_timedatetime.now())七、cron vs interval怎么选场景推荐触发器每天早上8点、晚上20点定点执行cron每周一、周五凌晨2点跑报表cron每10分钟轮询一次不关心整点interval9‑18点之间每30分钟执行cron不管什么时间从上一次结束算起间隔N秒interval简单记忆固定时间点用cron固定间隔时长用interval。注意interval是“任务启动后间隔N时间再跑”不受任务执行耗时影响cron是看系统时钟到点就触发。八、动态修改 cron 规则线上不需要删除重建job可以直接修改触发器参数# 修改job的cron规则改为每天10点、16点执行jobscheduler.get_job(demo_cron_job)job.modify(triggerCronTrigger(hour10,16,minute0,second0))九、总结APScheduler 的 cron 支持秒级与Linux crontab表达式不能直接复制字段顺序不一样。day和day_of_week是或逻辑同时限制需要在业务代码中做判断。生产环境务必指定时区timezoneAsia/Shanghai规避夏令时问题。耗时任务配置max_instances1防止任务并发重跑。定点时间选cron间隔轮询优先选interval。需要程序启动立刻执行添加next_run_timedatetime.now()。写cron规则后建议本地调试观察实际触发时间确认是否符合预期避免上线才发现时间错位。如果你需要我可以再补充一篇「cron表达式调试小工具」的代码片段方便本地测试你的cron配置会在哪些时间点触发。