You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于Heroku Scheduler实现仅在12am、12pm后各执行一次的定时任务?

解决方案:利用脚本内时间校验+临时文件标记

绝对可以实现!我之前在Heroku上处理过类似的定时任务需求,刚好能避开Scheduler的那些限制,而且完全不用数据库。下面给你具体的思路和代码示例:

核心思路

Heroku Scheduler的不确定性确实麻烦,但我们可以把「调度判断」从Scheduler转移到任务脚本内部:

  • 用Heroku Scheduler的每小时执行一次任务(这样能覆盖每天的0点和12点窗口)
  • 脚本启动时先做时间校验:只有当前时间是目标小时(12am/12pm)的前10分钟内,才执行实际任务
  • 用临时文件标记同小时内是否已执行,避免崩溃重试导致重复运行

具体实现步骤

1. 统一时区

首先要明确你用的时区,Heroku默认是UTC,如果你的12am/12pm是本地时间,记得在脚本里转换。比如用UTC的0点对应12am,12点对应12pm,这样最省事。

2. 编写带时间校验的脚本

这里用Python举个例子,其他语言逻辑完全通用:

import datetime
import os

def generate_shift_tasks():
    """生成班次任务的核心逻辑,替换成你的实际代码即可"""
    print("开始生成当前班次的任务...")
    # 你的任务代码写在这里

def main():
    # 用UTC时间,如需本地时区可替换(比如Asia/Shanghai)
    now = datetime.datetime.utcnow()
    current_hour = now.hour
    current_minute = now.minute
    date_hour_key = now.strftime("%Y%m%d_%H")  # 日期+小时的唯一标识

    # 目标小时:0=12am UTC,12=12pm UTC
    target_hours = {0, 12}

    # 第一步:检查是否在目标小时的前10分钟窗口内(适配Heroku的调度误差)
    if current_hour not in target_hours or current_minute >= 10:
        print("当前时间不在目标窗口,直接退出")
        return

    # 第二步:检查是否已经执行过(用临时文件标记,避免同窗口重复执行)
    marker_file = f"/tmp/shift_task_{date_hour_key}"
    if os.path.exists(marker_file):
        print("本小时内已执行过任务,退出")
        return

    # 第三步:执行实际任务
    generate_shift_tasks()

    # 创建标记文件,防止重试重复执行
    with open(marker_file, "w") as f:
        f.write("executed")
    print("任务执行完成,已创建标记文件")

if __name__ == "__main__":
    main()

为什么这个方案可行?

  • 适配Heroku Scheduler的不确定性:每小时执行的任务可能在整小时后的任意时间启动,但我们给了10分钟的窗口,足够覆盖Scheduler的误差范围
  • 避免重复执行:临时文件标记会在同一个dyno的重试中保留,确保同小时内只执行一次;而dyno销毁后临时文件会自动消失,不会影响第二天的任务
  • 无需数据库:完全依赖时间判断和临时文件,没有外部存储依赖,符合你的需求

部署到Heroku

在Heroku后台的Scheduler里添加一个每小时执行一次的任务,命令就是运行你的脚本,比如:

python shift_task_generator.py

这样设置后,脚本每天只会在UTC的0点和12点的前10分钟内执行一次,完美符合你的要求!

内容的提问来源于stack exchange,提问作者Tinker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:41:45