如何在 Heroku 上安排“每周”工作?

Posted

技术标签:

【中文标题】如何在 Heroku 上安排“每周”工作?【英文标题】:How can I schedule a 'weekly' job on Heroku? 【发布时间】:2012-04-07 18:29:52 【问题描述】:

我在 Heroku 上部署了一个 Rails 应用程序,其中 Heroku 调度程序插件成功地用于日常工作。

现在我想要每周工作,但调度程序插件不允许我每周选择。

关于如何完成此任务的任何建议:

我过去曾尝试使用 rufus-scheduler,但它给我带来了一些问题,所以这不是一个选择。有关详细信息,请参阅here。 我正在考虑在日常工作中检查当天的情况。有没有人尝试过并有反馈或知道该方法的问题? 非常感谢其他想法。

【问题讨论】:

【参考方案1】:

一种方法是您的第二个要点:

激活 Heroku cron 插件,并在 app/lib/tasks 中添加 cron.rake 任务

激活 Heroku 调度器插件,并在app/lib/tasks 中添加一个scheduler.rake 任务

task :your_weekly_task=> :environment do
  if Time.now.friday? # previous answer: Date.today.wday == 5
    #do something
  end
end

您甚至可以定义您希望任务运行的日期;o) (5 代表星期五)

编辑:顺便说一下,Cron 已被弃用,Heroku 建议切换到他们的调度程序插件。不过,这不会改变每周工作的方法。

EDIT2:根据 sunkencity 的反馈调整我的答案。

【讨论】:

cron 插件已被弃用,将停止使用,取而代之的是调度程序。也就是说,您建议的方法是合理的,但可以通过 activesupport 更好地制定:Time.now.friday? 我对硬编码这一天的想法感到畏缩,所以我暂时将这个问题留待更好的选择。 顺便说一句,我所做的是在一周中的某一天使用 heroku 配置变量来运行。然后,您必须通过 UI 控制一天中的时间。这真的很棒。 Heroku 团队,如果您在那里阅读此内容,请改进调度程序。它不必具有 cron 的所有灵活性。但是,至少可以安排每周和每月的工作。 我想出的一个小改进是使用一些元编程来完成每天的任务,例如your_weekly_task_monday, your_weekly_task_tuesday 等。然后你可以根据你希望它运行的日期在 heroku 调度程序中添加你想要的任务,所以你不要把这个配置放在应用程序中。 如果您想在每月的第一天(或每月的任何一天)发送报告,您可以这样做:if Time.now.day == 1【参考方案2】:

仅使用 shell 代码的替代选项。每小时设置 Heroku 调度程序,并与 date 命令进行比较:

# setting the schedular to run hourly at *:30 is equivalent to the 
# crondate: 30 8 * * 1
if [ "$(date +%H)" = 08 ] && [ "$(date +%d)" = 01 ]; then YOUR_COMMAND ; fi 

我已使用此代码在我的本地时区模拟 cron:

nz_hour="$(TZ=NZ date +%H)" ; nz_day="$(TZ=NZ date +%d)" ; if [ "$nz_hour" = 08 ] && [ "$nz_day" = 01 ]; then YOUR_COMMAND ; fi 

【讨论】:

【参考方案3】:

这并不理想,但我已经开始添加一个 RUN_IF 环境变量来通过 heroku:scheduler 运行任务,这让我可以每周和每月安排工作。

# lib/tasks/scheduler.rake
def run?
  eval ENV.fetch('RUN_IF', 'true')
end

def scheduled
  if run?
    yield
  else
    puts "RUN_IF #ENV['RUN_IF'].inspect eval'd to false: aborting job."
  end
end

# lib/tasks/job.rake
task :job do
  scheduled do
    # ...
  end
end

如果在没有 RUN_IF 变量的情况下运行 rake 任务,它将运行。否则,作业将被中止,除非 RUN_IF 的值评估为假值。

$ rake job                              # => runs always
$ rake job RUN_IF='Date.today.monday?'  # => only runs on Mondays
$ rake job RUN_IF='Date.today.day == 1' # => only runs on the 1st of the month
$ rake job RUN_IF='false'               # => never runs (not practical, just demonstration)

与上述其他想法类似,但我更喜欢将调度细节从应用程序代码中移出。

【讨论】:

【参考方案4】:

正如 over here 所讨论的,并使用 Rob 的上述逻辑,这里是按一周中的一天、一个月一次和特定日期分解的 bash 脚本。

每周一运行一个任务:

if [ "$(date +%u)" = 1 ]; then MY_COMMAND; fi

每月第一天运行一次任务:

if [ "$(date +%d)" = 01 ]; then MY_COMMAND; fi

您也可以在每年的 12 月 24 日运行一项工作:

if [ "$(date +%m)" = 12 ] && [ "$(date +%d)" = 24 ]; then MY_COMMAND; fi

【讨论】:

【参考方案5】:

如果您不想或不能使用 Rake 执行此操作,另一种选择是使用 bash 中的 Ruby 执行此操作:

#!/bin/bash

cmd="echo your schedule job here"

# Only run on even days
ruby -e 'if Time.now.utc.day.even?; puts "Not today!"; exit 1; end' && $cmd "$@"

这甚至适用于非 ruby​​ 项目(在我的例子中:Clojure)。

【讨论】:

以上是关于如何在 Heroku 上安排“每周”工作?的主要内容,如果未能解决你的问题,请参考以下文章

如何在android中每周安排闹钟?

如何安排脚本定期运行?

如何在解析服务器上使用 kue 安排作业?

在 Heroku 上运行 Django/React 应用程序时,如何让 collectstatic 工作?

如何让 mod_rewrite 在 Heroku 上工作?

如何安排在上午 9 点执行代码