【问题标题】:Whenever cron jobs fail to run每当 cron 作业无法运行时
【发布时间】:2015-03-22 13:49:51
【问题描述】:

我正在尝试使用 whenever gem 在我的应用程序中运行 cron 作业。我想每两分钟重新计算一次我的模型“用户”的属性“值”。以下是我采取的步骤:

宝石文件

gem 'whenever', :require => false

终端

$ bundle install
$ wheneverize .

schedule.rb

every 2.minutes do
  runner "User.recalculate"
end

models/user.rb

def self.recalculate
  User.all.each {|user| user.recalculate_value }
end

private

def recalculate_value
  self.value = self.value + 1
  self.save!
end

终端

$ whenever --update-crontab

和 '$when -l' 返回:

0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58 * * * * /bin/bash -l -c 'cd /home/website && bin/rails runner -e development '\''User:recalculate'\'''

但到目前为止,我的User.values 没有任何变化。在我的控制台中运行User.recalculate 可以正常工作,因此错误显然出现在任何时候。我错过了什么?

【问题讨论】:

  • 您能否提供任何日志或输出以使问题更清楚?
  • @StanislavMekhonoshin 日志或从哪里输出?
  • 当您通过 crontab 运行时,它会将消息写入 syslog。您也可以尝试在 Rails 控制台中运行 User.recalculate,只是为了检查代码是否正常运行,这是任何时候出现的问题。
  • @StanislavMekhonoshin 好的,我知道我错过了一些东西。什么是系统日志/我在哪里可以找到它? User.recalculate 有效,因此无论何时都存在问题。
  • 你有什么操作系统?我的意思是你什么时候在什么环境下运行?你具体是怎么运行的?

标签: ruby-on-rails ruby cron crontab whenever


【解决方案1】:

我快速创建了一个新的 Rails 应用程序来尝试重现您的问题,您可以在此处找到它,克隆它并亲自查看。

https://github.com/mlainez/stackoverflow-28111330/blob/master/app/models/user.rb

您要做的第一件事是验证运行器在什么环境中运行。默认情况下,无论何时使用production。如果您在本地计算机上,请务必在 schedule.rb 中将其设置为 development 或查看文档以了解如何更新 crontab 并设置正确的环境。

https://github.com/mlainez/stackoverflow-28111330/blob/master/config/schedule.rb#L7

这是您应该在 crontab 中看到的内容:

0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58 * * * * /bin/bash -l -c 'cd /Users/marc/Projects/stack && bin/rails runner -e development '\''User.recalculate'\'''

注意它说的是rails runner -e development 而不是production

另一件事是 basia 是对的。当我离开private 关键字并尝试在rails c 中执行User.recalculate 时,它会失败并显示:

private method `recalculate_value' called for #<User ...>

我很惊讶它可以在您的控制台中使用 private 关键字...您正在尝试访问实例上的私有方法。这在 Ruby 中是不可能的。您只能从外部访问实例的公共方法(除非您使用send(:method))。

删除 private 关键字修复了它,任务每两分钟按预期运行一次。

我在我的 github 代码中使用 Rails 4.2.0 和 ruby​​ 2.1.0。

编辑

确保您的 cron 守护程序正在运行:

service cron status

我还注意到,在您的 crontab 输出中,您有:

bin/rails runner -e development '\''User:recalculate'\''

注意Userrecalculate 之间的:。您一定是在您的日程安排中打错了。rb

它应该是.,因为它是一个方法调用。

另外,您可能想检查whenever -lcrontab -l 的输出是否相同。如果crontab -l 不同或为空,则说明您没有正确使用whenever --update-crontabwhenever -w,或者您使用的任何版本都可能有问题。

【讨论】:

  • 我需要做些什么来初始化 cron 吗?我将默认环境更改为开发,将所有代码移出private 部分,然后重新启动服务器,但它仍然没有运行任务。我更新了上面的$ whenever -l 输出。
  • 好吧,我知道我错过了一些重要的东西。 $ service crond status 返回“crond:无法识别的服务”。如何运行 cron 守护进程?
  • 这很奇怪。那么它可能只是service cron status,最后没有'd'(对不起,我在OSX上)。 Cron 应该默认安装在 Ubuntu 上。要启动它或重新启动它,请使用service cron startservice cron restart。您可能必须使用 sudo 来执行此操作。
  • cron 应该在 Ubuntu 上默认启动时运行,我很惊讶它在你的情况下没有,但我不是 Ubuntu 专家......要将服务添加到默认运行级别,请使用sudo update-rc.d cron defaultssudo update-rc.d cron enable 如果由于某种原因被禁用。
  • 我想补充的一点是,您可以在/var/log/syslog 中查看 cron 日志,并且可以使用tail -f /var/log/syslog 将其“实时”可视化。玩得开心!
【解决方案2】:

删除private,因为现在运行User.recalculate 将失败并出现private method 'increment' called for #&lt;User&gt; 错误。

顺便说一句,User 是 ActiveRecord 类吗?因为有 increment http://apidock.com/rails/ActiveRecord/Base/increment 方法和 increment!(保存记录),所以最好将方法名称更改为其他名称或仅使用 user.increment!(:value)

【讨论】:

  • 是的,它是一个 ActiveRecord 类。感谢您的提示,我将increment 更改为recalculate_value
  • 我将private 留在了其中,但在控制台中运行User.recalculate 有效,所以我认为我的models/user.rb 代码中没有任何问题。
【解决方案3】:

您似乎没有在您的方法increment 中保存您的用户。试试这个:

def increment
  self.value = self.value + 1
  self.save
end

【讨论】:

  • 哦,那是个错误。我正在保存我的原始代码:我更新了问题。
猜你喜欢
  • 1970-01-01
  • 2015-09-20
  • 1970-01-01
  • 2014-02-02
  • 1970-01-01
  • 2017-11-05
  • 1970-01-01
  • 2011-09-27
  • 1970-01-01
相关资源
最近更新 更多