3

I am trying to solve a bit a of mystery here... We have created an gem which is called via cron.

The mystery is: This works on machine A but not on machine B the environments are identical as far as I can tell.

Both machines are Mac OS X 10.6.

I also understand cron runs things in a minimalistic environment.

crontab:

10 2 * * * /Users/michael/.rvm/gems/ruby-1.9.3-p194/bin/my_gem

The error on machine B is:

/Users/michael/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/site_ruby/1.9.1/rubygems/dependency.rb:247:in `to_specs': Could not find my_gem-toolchain (>= 0) amongst [bigdecimal-1.1.0, io-console-0.3, json-1.5.4, minitest-2.5.1, rake-0.9.2.2, rdoc-3.9.4] (Gem::LoadError)
    from /Users/michael/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/site_ruby/1.9.1/rubygems/dependency.rb:256:in `to_spec'
    from /Users/michael/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/site_ruby/1.9.1/rubygems.rb:1231:in `gem'
    from /Users/michael/.rvm/gems/ruby-1.9.3-p194/bin/my_gem:22:in `<main>'

Here is the contents of /Users/michael/.rvm/gems/ruby-1.9.3-p194/bin/my_gem

#!/Users/michael/.rvm/rubies/ruby-1.9.3-p194/bin/ruby
#
# This file was generated by RubyGems.
#
# The application 'my_gem-toolchain' is installed as part of a gem, and
# this file is here to facilitate running it.
#

require 'rubygems'

version = ">= 0"

if ARGV.first
  str = ARGV.first
  str = str.dup.force_encoding("BINARY") if str.respond_to? :force_encoding
  if str =~ /\A_(.*)_\z/
    version = $1
    ARGV.shift
  end
end

gem 'my_gem-toolchain', version
load Gem.bin_path('my_gem-toolchain', 'my_gem', version)

Line 22 is: gem 'my_gem-toolchain', version

Here is the output of running env via cron on both machines:

SHELL=/bin/sh
USER=michael
PATH=/usr/bin:/bin
PWD=/Users/michael
SHLVL=1
HOME=/Users/michael
LOGNAME=michael
_=/usr/bin/env

I believe this has to do with the GEM_PATH not being set. However, on machine A the GEM_PATH appears not to be set but everything is working.

I would like to have a better understanding as to the workings of ruby. Apparently I am still missing something.

Why does this work on machine A but not on machine B?

Michael
  • 3,568
  • 3
  • 37
  • 50

1 Answers1

2

RVM is a great tool for developers to maintain their environments, but it's a nightmare in production. Once you're executing things from cron, you're essentially "in production" for the purposes of maintaining an execution environment, even if it happens to be cron on your dev machine.

I recommend you install the gem system-wide and run it from a script which makes no assumptions about where it's installed. Make sure you follow all the best practices for creating a gem so that your gem's dependencies are correctly installed and the binaries are handled properly, etc. Once you've built the gem, you should install it via the system Ruby so that it's available to all users in the default location for your OS's Ruby interpreter, and all its dependencies are installed.

Check out Rubygems's Make your own gem guide for best practices.

Then install the resulting gem file using the system ruby instead of into your RVM directory:

rvm use system
gem install my-gem-1.0.0.gem

That should get everything setup so that it runs happily from cron and for any user. You probably don't want to be running cron jobs that rely on RVM in your home directory.

To specifically address your question, there are a number of reasons it might work on A but not B. If you installed the gem system-wide on one machine and via RVM on the other, that'll effect where the dependencies were installed (system-wide vs. in your home directory); if you don't even have RVM on the other machine then that's definitely the case. It could be that your Gem doesn't properly declare its dependencies, so that when you installed it on machine B, the dependencies weren't installed there, but you manually installed them on machine A during development. It could be that you've got the same gems installed on both, and the home directory is shared, and everything else appears to be duplicated, but the RVM magic in your shell config isn't executing on both. Could be different users, thus different environments. Whatever the underlying cause, just take RVM out of the equation and follow the rubygems guidelines and you'll be good.

Jim Stewart
  • 16,964
  • 5
  • 69
  • 89