在自己的目录之外运行一个Bundler部署的Ruby应用程序?

时间:2011-07-31 13:48:07

标签: ruby rubygems bundler

我正在编写一个基于Ruby的守护进程,以便在我的一个Ubuntu服务器上运行。我希望这能在启动时运行,因此将为它编写一个upstart作业文件。但是,我使用了bundler来管理它使用的各种gem,并打算在将它部署到服务器后执行此操作:

bundle install --deployment

这使捆绑器进入所谓的“部署模式”,从而设置了各种选项,并且所有宝石都安装在“供应商”目录中而不是系统范围内。然而,这会产生运行它的问题,因此它必须从它自己的目录执行,因为这是宝石最终的地方:

<in the app's dir>
$ ./runmyapp
<it runs>

如果我cd到另一个位置,然后尝试使用它的完整路径运行它,则会失败:

<in another directory>
$ /path/to/runmyapp
<it crashes as it can't locate its gems>

我已阅读了大量的捆绑文档,这整个场景甚至从未被涵盖过?我应该将宝石安装到系统中吗?我还有什么别的吗?

3 个答案:

答案 0 :(得分:33)

您使用bundler作为应用的gem manager。我认为在这种情况下使用bundle exec是运行可执行文件的最佳方式。

如果您从包含Gemfile的目录以外的目录运行您的应用程序,则应通过设置BUNDLE_GEMFILE来设置Gemfile位置(请参阅bundle help exec)。以下将帮助您:

BUNDLE_GEMFILE=/path/to/Gemfile bundle exec /path/to/runmyapp

答案 1 :(得分:0)

我自己解决了类似的问题,最后我创建了一个包装器脚本,

#!/bin/bash
BUNDLE_GEMFILE="$(dirname $0)"/Gemfile bundle exec ruby "$(dirname $0)"/app.rb $*

app.rb是应用程序的“主要”入口点。您可以调用包装脚本runmyapp或应用程序的名称或其他名称。

注意:$0由bash设置为包装脚本的文件位置,例如/home/foo/app/runmyapp./runmyapp

bundle exec“执行命令,使Gemfile中指定的所有gem都可以在Ruby程序中使用。” (docs

答案 2 :(得分:0)

这里有一些很好的答案,但是我想我会添加一个适用于我的场景的快速答案,在该场景中,我通过调用Bundler来显式设置Bundler.require,并且不要通常不会通过bundle exec执行脚本。

如果执行此操作,并且Gemfile / Gemfile.lock文件与脚本位于同一目录中,则可以使用Dir.chdirKernel.__dir__的组合,例如所以:

  Dir.chdir(__dir__) { Bundler.require }

这可以通过在返回原始目录之前将调用目录更改为Bundler.require(因为它希望相关文件存在于当前工作目录中)来实现。