Rails.root 在 Resque 作业期间指向生产中的错误目录

Posted

技术标签:

【中文标题】Rails.root 在 Resque 作业期间指向生产中的错误目录【英文标题】:Rails.root points to the wrong directory in production during a Resque job 【发布时间】:2013-09-20 04:23:13 【问题描述】:

我有两个同时排队的工作,一个工作人员连续运行它们。这两个作业都从我的 Rails 项目根目录中的builds/ 目录中复制一些文件,并将它们放入一个临时文件夹中。

第一个作业总是成功的,从来没有问题 - 哪个作业先运行也没有关系。第一个会起作用。

第二个在尝试复制文件时收到此错误:

没有这样的文件或目录 - /Users/apps/Sites/my-site/releases/20130829065128/builds/foo

该版本文件夹已有两周的历史,不应仍在服务器上。它是空的,只有一个 public/uploads 目录,没有别的。我已经杀死了所有的工人并多次重新启动它们,并多次重新部署了 Rails 应用程序。当我删除该发布目录时,它会再次出现。

我现在不知道该怎么办。为什么这个工人总是在这个旧的发布目录中创建/查看?为什么只有第二个工人会这样做?我正在使用以下方法获取路径:

Rails.root.join('builds') - Rails.root 显然是 2 周前的 capistrano 版本?我还应该提到这只发生在生产环境中。我能做些什么 ?

【问题讨论】:

这个工人可能是从那个特定版本中部署的代码中产生的。假设没有其他东西可以是那个路径名的来源 我怀疑您有一个代码可以更改 rails env 中的目录。您的代码中是否引用了Dir.chdir?请查看以下文档以供参考:ruby-doc.org/core-2.1.2/Dir.html#method-c-chdir 【参考方案1】:

Rescue 没有在部署中重新启动(停止和启动),这导致旧版本的代码运行。每个工作人员继续为队列服务,从而导致奇怪的错误或行为。

根据路径名,您似乎正在使用 Capistrano 进行部署。

您在使用capistrano-resque gem 吗?如果没有,你应该看看。

【讨论】:

【参考方案2】:

我遇到了同样的问题,我是这样解决的:

在我的例子中,问题是 capistrano 如何处理 PID 文件,这些文件指定当前存在哪些工作人员。这些文件通常存储在tmp/pids/。您需要告诉 capistrano 不要将它们存储在每个发布文件夹中,而是在 shared/tmp/pids/ 中。否则,在您进行新部署后,resque 不知道当前正在运行哪些工作程序。它查看新版本的 pids 文件夹并没有找到任何文件。因此,它假定不存在需要关闭的工人。 Resque 只是创造了新的工人。并且所有其他工作人员仍然存在,但您无法在 Resque-Dashboard 中看到它们。如果您检查服务器上的进程,您只能看到它们。

这是您需要做的:

在您的 deploy.rb 中添加以下行(顺便说一句,我使用的是 Capistrano 3.5)

append :linked_dirs, ".bundle", "tmp/pids"
set :resque_pid_path, ->  File.join(shared_path, 'tmp', 'pids') 

在服务器端,在终端运行htop启动htop,然后按T,查看当前正在运行的所有进程。很容易发现所有这些 resque-worker-processes。您还可以看到附加到它们的发布文件夹的名称。

您需要手动杀死所有工作进程。退出 htop 并键入以下命令以终止所有 resque 进程(我希望它完全干净):

sudo kill -9  `ps aux | grep [r]esque | grep -v grep | cut -c 10-16`

现在您可以进行新的部署了。您还需要重新启动 resque-scheduler。

希望对你有帮助。

【讨论】:

以上是关于Rails.root 在 Resque 作业期间指向生产中的错误目录的主要内容,如果未能解决你的问题,请参考以下文章

Resque作业,如何停止正在运行的作业

以编程方式获取 Resque 队列中的作业数

如何在 AWS Elastic Beanstalk 上使用 Resque 运行 Rails 后台作业?

ruby 在Resque 1.x中有选择地删除/重试失败的作业

ruby 在Resque 1.x中有选择地删除/重试失败的作业

如何破坏由resque工人排队的工作?