生产环境下Resque作业中Rails.root指向错误目录

9

我有两个工作同时排队,一个工人接着运行它们。这两个工作都从根目录下的builds/目录中复制一些文件,并将它们放到临时文件夹中。

第一个工作总是成功的,从来没有问题 - 不管哪个工作先运行。第一个工作总是有效的。

第二个工作在尝试复制文件时收到以下错误:

没有那个文件或目录 - /Users/apps/Sites/my-site/releases/20130829065128/builds/foo

那个 releases 文件夹已经两周了,不应该还在服务器上。它是空的,只有一个 public/uploads 目录,没有其他东西。我已经杀死了所有的工人并多次重新启动它们,也多次重新部署了 Rails 应用程序。但当我删除那个 releases 目录时,它会再次创建。

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

Rails.root.join('builds') - Rails.root 显然是一个两周前的 Capistrano 发布版本?我应该还提一下,这只发生在生产环境中。我该怎么办?


2
这个工人很可能是从部署在那个特定版本中的代码产生的..假设没有其他东西可以成为该路径名的起源。 - prusswan
我怀疑你的代码在Rails环境中更改了目录。你的代码中是否有对Dir.chdir的引用?请参考以下文档:http://www.ruby-doc.org/core-2.1.2/Dir.html#method-c-chdir - Iuri G.
2个回答

0

在部署过程中,救援程序没有重新启动(停止和启动),导致旧版本的代码被运行。每个工作进程继续服务于队列,导致出现奇怪的错误或行为。

根据路径名,看起来您正在使用Capistrano进行部署。

您是否正在使用capistrano-resque gem?如果没有,建议您尝试一下。


0

我曾经遇到过完全相同的问题,这是我解决它的方法:

在我的情况下,问题出在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进程。您还可以看到它们附加的release-folder的名称。
您需要手动杀死所有worker进程。退出htop并键入以下命令以杀死所有resque进程(我喜欢完全清除它):
sudo kill -9  `ps aux | grep [r]esque | grep -v grep | cut -c 10-16`

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

希望这能帮到您。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接