Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Run a bundler-deployed Ruby app outside of its own directory?

I'm in the process of writing a Ruby-based daemon to sit and run on one of my Ubuntu servers. I'll be wanting this to run on startup, so will be writing an upstart job file for it. However, I've used bundler for managing the various gems it uses and intend to do this after deploying it to the server:

bundle install --deployment

This puts bundler into the so-called 'deployment mode', whereby various options are set and all the gems are installed into a 'vendor' directory rather than system-wide. However this creates a problem with running it, whereby it must be executed from its own directory as this is where the gems end up:

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

If I cd to a different location and then try to run it using it's full path, it fails:

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

I've read through lots of bundler documentation and this entire scenario is never even covered? Should I just install the gems to the system instead? Is there something else I ought to do?

like image 295
Mark Embling Avatar asked Jul 31 '11 13:07

Mark Embling


People also ask

Where does bundle install run?

Install Bundler Select Tools | Bundler | Install Bundler from the main menu. Press Ctrl twice and execute the gem install bundler command in the invoked popup. Open the RubyMine terminal emulator and execute the gem install bundler command.

What is bundle exec?

bundle exec is a Bundler command to execute a script in the context of the current bundle (the one from your directory's Gemfile). rake db:migrate is the script where db is the namespace and migrate is the task name defined.


3 Answers

You use bundler as gem manager for your app. I think in this case using bundle exec is the best way to run executables.

If you run your app from different directory than directory that contains Gemfile you should set Gemfile location by setting BUNDLE_GEMFILE (see bundle help exec). Following will help you:

BUNDLE_GEMFILE=/path/to/Gemfile bundle exec /path/to/runmyapp
like image 140
petRUShka Avatar answered Oct 15 '22 14:10

petRUShka


Tackling a similar problem myself I ended up creating a wrapper script,

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

Here app.rb is the app's "main" entry point. You might call the wrapper script runmyapp or the app's name or whatever.

Note: $0 is set by bash to the wrapper script's file location, e.g. /home/foo/app/runmyapp or ./runmyapp

bundle exec "executes the command, making all gems specified in the Gemfile available to require in Ruby programs." (docs)

like image 39
tantrix Avatar answered Oct 15 '22 16:10

tantrix


There are some good answers here, but I thought I'd add a quick answer that works in my scenario, where I am explicitly setting up Bundler with a call to Bundler.require, and don't often execute the script via bundle exec.

If you are doing this, and the Gemfile/Gemfile.lock files are in the same directory as the script, you can use a combination of Dir.chdir and Kernel.__dir__ like so:

  Dir.chdir(__dir__) { Bundler.require }

This works by changing the directory for the call to Bundler.require (as this expects the relevant files to exist in the current working directory) before returning to the original directory.

like image 1
msbit Avatar answered Oct 15 '22 16:10

msbit