Before I get started some quick defninitions:
- Ruby : a programming language
- rvm : Ruby Version Manager, tool for managing rubies
If you’ve had to work with multiple versions of Ruby in the past, the power of rvm is very compelling. Gone are the headaches of trying to get multiple versions to coexist nicely on a single box. Gone are the headaches of hosing the core installation of Ruby that various OS based tools may rely on. Instead you’re given a very clean and elegant interface from which you can switch to different Ruby’s and also switch between various gem sets within a given Ruby.
rvm’s documentation for the most part is excellent, about the only thing that isn’t obvious is how to harness rvm’s power for shell scripts and CGI scripts based on Ruby. So below is my attempt to try and put some structure around how shell & CGI scripts can also harness the power of rvm.
I’m not going to really discuss how to setup/install rvm. I’ll leave that up to the excellent getting started docs over on the rvm site. So let’s just assume that you’ve got some mix of rubies installed.
For my scenario I installed the following:
- rvm install 1.8.7
- rvm install 1.9.2
- rvm install ree
NOTE: I installed rvm as a system installation (aka. root install), so it’s installed in this directory: /usr/local/rvm.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
# contents of rvm's dir. /usr/local/rvm |-- LICENCE |-- README |-- VERSION |-- archives |-- bin |-- config |-- environments |-- examples |-- gems |-- gemsets |-- help |-- lib |-- log |-- patches |-- rubies |-- scripts |-- src |-- tmp |-- user `-- wrappers
By default rvm creates a set of wrapper scripts which live in this directory /usr/local/rvm/wrappers.
1 2 3 4 5 6 7 8 9 10
# wrappers dir. /usr/local/rvm/wrappers |-- default -> /usr/local/rvm/wrappers/ruby-1.9.2-p180 |-- ree-1.8.7-2011.03 |-- ree-1.8.7-2011.03@global |-- ruby-1.8.7-p334 |-- ruby-1.8.7-p334@global |-- ruby-1.9.2-p180 `-- ruby-1.9.2-p180@global
rvm then makes links in /usr/local/bin that point to the various wrapper scripts in the wrappers directory mentioned above.
1 2 3 4 5 6 7 8
# links to wrappers /usr/local/bin ... |-- ree-1.8.7-2011.03 -> /usr/local/rvm/wrappers/ree-1.8.7-2011.03/ruby |-- ruby-1.8.7-p334 -> /usr/local/rvm/wrappers/ruby-1.8.7-p334/ruby |-- ruby-1.9.2-p180 -> /usr/local/rvm/wrappers/ruby-1.9.2-p180/ruby ...
So all these links, & wrapper scripts, & actual ruby binaries can be bit overwhelming. Plus it’s not really all that clear which ones to use for shell & CGI scripts. So based on my experience with working with UNIX/Linux I believe the best/appropriate way to use the rvm wrapper scripts is like so:
NOTE: Assuming you want the 1.9.2 version of ruby
Some explanation of what rvm is doing here. rvm creates wrapper scripts under this directory, /usr/local/rvm/wrappers. These scripts set environment variables like GEM_PATH & GEM_HOME. These are needed so that gems can get loaded correctly as part of a specific version of ruby. Links to these wrapper scripts are created under /usr/local/bin, when you do a system installation of rvm.
NOTE: If you’ve installed rvm as yourself they’re located here: $HOME/.rvm/bin.
It’s critical to start the shebang line (#!/….) with /usr/bin/env. Just trying to point it directly to a wrapper (for e.g. #!/usr/local/bin/ruby-1.9.2-p180) will not suffice. This is due to the fact that the wrapper scripts are not actually the ruby interpreters, (i.e. they aren’t binaries), they are shell scripts that are sourcing an environment set up prior to calling your script as an argument to a ruby interpreter, like so:
BTW: the $@ below is your shell script name being passed to ruby.
1 2 3 4 5
# snippet of wrapper script ... source "/usr/local/rvm/environments/ruby-1.9.2-p180" exec ruby "$@" ...
Finally here’s an example which demonstrates a script that runs in the cgi-bin directory:
1 2 3 4 5 6 7 8 9 10 11 12 13
#!/usr/bin/env /usr/local/bin/ruby-1.9.2-p180 puts "Content-Type: text/html" puts puts "<html>" puts "<body>" puts "<h1>Hello Ruby!</h1>" puts "<p>shebang: #!/usr/bin/env /usr/local/bin/ruby-1.9.2-p180</p>" puts "<p>RUBY_VERSION: " + RUBY_VERSION + "</p>" puts "<p>RUBY_PLATFORM: " + RUBY_PLATFORM + "</p>" puts "<p> RUBY_RELEASE_DATE: " + RUBY_RELEASE_DATE + "</p>" puts "</body>" puts "</html>"