我正在编写一个基于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>
我已阅读了大量的捆绑文档,这整个场景甚至从未被涵盖过?我应该将宝石安装到系统中吗?我还有什么别的吗?
答案 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.chdir
和Kernel.__dir__
的组合,例如所以:
Dir.chdir(__dir__) { Bundler.require }
这可以通过在返回原始目录之前将调用目录更改为Bundler.require
(因为它希望相关文件存在于当前工作目录中)来实现。