October 2014
M T W T F S S
« Mar    
 12345
6789101112
13141516171819
20212223242526
2728293031  
135

Refs

Categories

Archives

profile for slm on Stack Exchange, a network of free, community-driven Q&A sites

How to use rvm installs of Ruby in shell & CGI scripts

Background

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.

Getting Started

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
...

Solution

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:

1
#!/usr/bin/env /usr/local/bin/ruby-1.9.2-p180

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>"

Useful URLs

4 comments to How to use rvm installs of Ruby in shell & CGI scripts

  • Brad Landers

    I’ve been struggling with solving this exact problem: how to load a specific ruby and gemset in a shellscript. One snag, however. I don’t have any of the wrapper symlinks in /usr/local/bin. I’m assuming this is because I’m not running a system-wide install on my local machine. Do you know if this technique is still valid on the current version of RVM (1.8.1 at the time of commenting)?

    • Are you asking if the current version can be installed so that it includes /usr/local/bin symlinks? Sorry if I’m being dense but I just wanted to clarify your question.

    • I haven’t had a chance to try with the latest version 1.8.1 as root, but the main docs for rvm still include this comment:

      Multi-User Install Location: /usr/local/rvm

      If the install script is run as root, RVM will automatically install into /usr/local/rvm

      So I’d be inclined to assume that system installs are still supported. They’re referred to as multi-user installs and they happen when you install rvm as the root user.

  • Jørn Støylen

    Thank you for a very instructional and helpful article!

    I’ve been struggling with this for hours, and now it works thanks to you! :-)

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>