RVM: seriously?

August 24th, 2010 by lucas

There’s some hype in the Ruby community about RVM (Ruby Version Manager). It’s a tool that allows to switch between Ruby versions on the same system (much like what the alternatives system provides for Java on Debian, except that RVM does it either system-wide or per-user).

However, when you look at it, RVM looks quite scary.

The recommended installation instruction is:
bash < <( curl http://rvm.beginrescueend.com/releases/rvm-install-head ).
That script doesn’t use set -e, and actually does a git clone behind the scenes. Without first checking that git is installed. But if you don’t have git installed, it’s not a problem: there’s another script later on the page that downloads and compiles it for you.

After installing RVM itself, you need to install rubies (different ruby implementations). Use rvm install ree,1.9.2-head,jruby. That will automatically download and build the various versions in your homedir. It’s interesting to note the the compilation messages were probably too scary, and are not displayed.

But how does it handle the switch between different versions ? First, you need to add some magic to your .bashrc:
[[ -s "$HOME/.rvm/scripts/rvm" ]] && . "$HOME/.rvm/scripts/rvm"
or, for a system-wide install of rvm:
[[ -s "/usr/local/rvm/scripts/rvm" ]] && . "/usr/local/rvm/scripts/rvm"
And then, you can select your ruby implementation using rvm --default 1.9.2, for example. That works by redefining $PATH:
# echo $PATH
/usr/local/rvm/gems/ruby-1.9.2-p0/bin:/usr/local/rvm/gems/ruby-1.9.2-p0@global/bin:/usr/local/rvm/rubies/ruby-1.9.2-p0/bin:/usr/local/bin:/usr/local/bin:/usr/local/sbin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11

Of course, that’s quite fragile: if you are in one of the cases where bash doesn’t read .bashrc, or if you happen to be using dash, you lose.

Looking at the code of RVM itself, it is also very fragile: it’s pure bash, without any error handling. During my test (in a chroot), I often got error messages about missing commands that were apparently ignored. The installer insists on using colors, and spews lots of error messages if executed without a controlling tty. There are also some interesting code snippets like perl -e 'sleep 0.5'.

So, where do we go from here? Well, obviously, with my Debian hat, I’m not going to advocate a solution that makes everything possible to avoid the distribution’s packaging system, and I don’t see RVM being packaged in Debian anytime soon.
In Debian, we already provide co-installability of Ruby 1.8 and 1.9.2, and users are free to choose which one to use on a per-script basis, by running them with version-suffixed ruby executables. The ‘ruby’ executable itself still points to 1.8, as it’s clearly too early to make 1.9.2 the default. Many Ruby libraries are provided for both 1.8 and 1.9.2, and we plan to discuss changes in the packaging system to be able to make it easier to provide packages for both versions. There’s also recent work on packaging JRuby, but it’s quite hard as it requires removing all the non-free or undistributable parts, and packaging them separately.

45 Responses to “RVM: seriously?”

  1. Jeff Schroeder wrote on 08/24/10 at 11:58 pm :

    Python has virtualenv for the same basic idea. If you have time please update this blog with your thoughts on virtualenv as well:
    http://pypi.python.org/pypi/virtualenv

    A lot of django developers use it to test different python / django versions concurrently for different projects.

  2. Victor Costan wrote on 08/25/10 at 12:28 am :

    One of the main reasons we need RVM is that Ubuntu’s Ruby team is so slow in getting stuff packaged. I don’t need RVM to switch Ruby versions, I need it because it gives me Ruby 1.9.2. I need 1.9.2 because I use Rails 3, and it doesn’t work well in 1.9.1, and I want the speed improvements over the 1.8 series. In Ubuntu, ruby1.9 still points to the 1.9.0 version, which is not recommended for any use. Also, Ubuntu’s version of Rubygems is too old for Rails 3, and has system update disabled, so it’s pretty much useless.

    I understand that Rubygems doesn’t match Debian’s philosophy. But Ruby, Rails, and all the stuff they bring with them, have clear benefits and are here to stay. And if RVM lets me get to the software versions I need, and Debian packaging doesn’t, then I’ll go for RVM.

    Since you’re annoyed by RVM, I hope that you’ll make the Debian packages for Ruby so good that I won’t need to use it.

  3. Wayne E. Seguin wrote on 08/25/10 at 2:33 am :

    Lucas,

    Thank you for taking time to review RVM.

    Can you please update this post and offer realistic actionable suggestions on how to address each of your concerns instead of simply identifying them as ‘scary’.

    For example, I have already removed the perl code in the repository.

    Also, you do NOT need to source RVM for a root ‘system’ install and by specifying
    /usr/local/bin/rvm --default 1.9.2 for example, RVM will switch out the {ruby,irb,gem,rake} executables in /usr/local/bin/.

    ~Wayne

  4. James Healy wrote on 08/25/10 at 2:35 am :

    I agree that RVM is a hacky way to solve the problem of running concurrent ruby VMs, however with 1.9.2 current broken in testing and unstable it’s the easiest way to get a working version of YARV.

  5. Lucas wrote on 08/25/10 at 7:58 am :

    @Wayne: I think that a good start would be to use at least “set -e”. But shell scripts are notoriously difficult to get right, because you need to care about differences between, say, GNU coreutils and the freebsd equivalents. It would probably be better to assume that a system ruby is installed, and use it for RVM (and then rewrite all of RVM in Ruby).

  6. Lucas wrote on 08/25/10 at 8:01 am :

    @James: what is broken about 1.9.2 in testing and unstable ? Are you talking about rubygems integration ? (#588125 ?)

  7. Jon wrote on 08/25/10 at 10:42 am :

    Ugh, how unbelievably horrid!

    Victor, you don’t need RVM to get Ruby 1.9.2. You can install it by hand yourself, so it’s a false argument to suggest that RVM should be packaged on this basis.

    It is interesting that Ruby in Debian (thus Ubuntu) is so far behind upstream. I wonder why? There is very little list traffic on debian-ruby. Perhaps it’s simply a manpower problem.

  8. Jon wrote on 08/25/10 at 10:45 am :

    Update: Debian package up ‘ruby1.9.1′, which claims “This package provides version 1.9.2 series of Ruby, which is binary-compatible with the 1.9.1 branch.” The same package appears to be in Ubuntu Maverick. Victor, is this package not what you need?

  9. Lucas wrote on 08/25/10 at 10:49 am :

    Debian and Ubuntu aren’t behind on Ruby. Usually, what most distributions do is that they freeze the version they release with, and don’t update (except for security/serious bugs) the software after the release.

    We have the current status:
    Debian lenny (released in february 2009) has 1.9.0.2
    Debian squeeze (to be released before end of 2010) has 1.9.2
    Ubuntu:
    Karmic: 1.9.1.243
    Lucid: 1.9.1.378
    Maverick: 1.9.2 (probably)

    It’s true that “ruby1.9″ points to 1.9.0. You should use ruby1.9.1 (where 1.9.1 is the ruby compatibility version, not necessarily the ruby version) to get Ruby 1.9.1 or 1.9.2. It’s not our fault if upstream decided to break compatibility between 1.9.0 and 1.9.1/1.9.2, unfortunately. At least they did the right thing between 1.9.1 and 1.9.2, but it’s quite confusing for users now.

  10. poisonbit wrote on 08/25/10 at 1:54 pm :

    Hi, not the same, but maybe the code of perlbrew can give ideas.

    It JUST WORKS (the only requirement is apt-get install build-essential)

    curl -LO http://xrl.us/perlbrew
    chmod +x perlbrew
    ./perlbrew install

    http://search.cpan.org/perldoc?App::perlbrew#SYNOPSIS

  11. Jeff Schroeder wrote on 08/25/10 at 2:08 pm :

    @Lucas: Because you think shell scripts are notoriously difficult to get right does not mean that Wayne or myself agree. With a statement like that in fact, I think you just need to learn it more.

    Honestly writing a posix compatible (no bashism) shell script is not hard if you know what you’re doing. Also, making it do proper error checking isn’t much harder than in ruby/python/perl…

  12. Lucas wrote on 08/25/10 at 2:16 pm :

    @Jeff: usually, the difficult part is not “no bashisms”, it is “no GNUisms”.

  13. Jeff Schroeder wrote on 08/25/10 at 2:38 pm :

    And again, a lack of experience on your part does not equal it being difficult for the rest of the world. It is just a matter of doing it and understanding the differences.

  14. Lucas wrote on 08/25/10 at 2:52 pm :

    @Jeff: why do you assume a lack of experience on my part?

  15. Jeff Schroeder wrote on 08/25/10 at 3:07 pm :

    Because it isn’t much harder to properly code a bourne shell script without set -e to do the right things when it errors than it is to do in any other language. Use the right tool for the job. That is no excuse for crappy code.

  16. Lucas wrote on 08/25/10 at 3:10 pm :

    You mean adding || exit $? at the end of each line of the script? :-)

    Anyway, let’s not digress on the writing of shell vs e.g ruby scripts. There are ways to write well-written shell scripts that check for errors without set -e. But those other ways are not used by RVM AFAICS.

  17. Jeff Schroeder wrote on 08/25/10 at 3:16 pm :

    Good point. It wasn’t meant to come off as an attack so much as an observation. I’d love your thoughts on virtualenv when you get time though.

  18. Wayne E. Seguin wrote on 08/25/10 at 4:42 pm :

    There are ways to write well-written shell scripts that check for errors without set -e. But those other ways are not used by RVM AFAICS.

    ok. Please point to some good documentation on these methods that you suggest or explain them in detail on your blog.

    ~Wayne

  19. Lucas wrote on 08/25/10 at 5:53 pm :

    This page looks like a good start:
    http://www.davidpashley.com/articles/writing-robust-shell-scripts.html

  20. Don wrote on 08/26/10 at 8:13 pm :

    Even if you want to use MRI trunk, it’s easier, and safer, to simply clone their git repository</a and install. There's nothing difficult about the compilation process.

  21. Jérémy Lecour wrote on 08/28/10 at 3:20 pm :

    Hi Lucas,

    The shell part of RVM **might** have some room for improvement. I don’t really know because it’s not my area of expertise. But Wayne (and a few others) have put some much effort and energy in RVM that I’m sure he’s willing to learn and improve it.

    Besides that, I have the feeling that you’re missing some important parts of RVM and why it’s so much different (and better) than having 2 Ruby binaries installed (1.8 and 1.9) as possible on Debian.

    First, there are not only one 1.8 and 1.9 versions. There are many minor versions still widely used and some different implementations “inside” the 1.8 branch. In the end a developer may need to test his code against a dozen of Ruby versions (or more)

    Then RVM brings the concept of isolation, up from the Ruby binaries (ruby, rake, gem, …) down to the installed gems. I’m not aware of another, equally easy to use, way of doing this, and I guess that’s why RVM has been gaining so much popularity for the last year.
    The use of .rvmrc files is immensely useful in the development environment (I’ve blogged about this here : http://wp.me/p6W-4p).

    Finally, RVM makes possible to run some code against many rubies and/or gemsets all at once. That’s the RVM set operations. I’m not using them yet, but it is something else that having 2 rubies in the system doesn’t seem to make possible.

    I’ll end this by saying that I’ve been a big fan of Debian, way before knowing Ruby, and I know both want to organize things their way (especialy regarding the gems, …).
    As a passionate devop, it has not been that difficult to make them live well under the same roof. In the end, it’s all good for me.

  22. Evan Dorn wrote on 08/31/10 at 10:51 pm :

    While I do use RVM for switching ruby versions, it’s actually more important to me to use for managing gemsets.

    Despite all the best efforts of gem developers, gems do generate interdependencies and trying to maintain different projects for different clients that use different groups of gems can only be accomplished sometimes when my development environment can manage gemsets intelligently.

    I have no trouble believing that RVM’s code itself is brittle, and could probably be better. But it’s so dramatically much better than what we had before, which was nothing. Maybe RVM2 will be a proper full application that’s written in Ruby itself and is well tested … but in the meantime I applaud Wayne Seguin for his efforts and for giving us a usable tool to solve a real problem developers face.

  23. Akoor Watt wrote on 09/3/10 at 8:54 am :

    Really badly designed script getting popular is dangerous for us, I have looked at the code as well and this is really a piece of sh***. Why don’t they go native with a ruby script or a ant rules (or equivalent in Ruby)

  24. Jeremy Lecour wrote on 09/3/10 at 9:32 am :

    @Akoor. Thanks for the support. If you admit that RVM is useful but badly designed, maybe you could start by contributing in a more positive way. I could be to tell what is bad, how it could be improved, …

    I don’t know why, but I guess that if Wayne choose to make shell scripts instead of Ruby, he may have thought about it (being more a ruby developer)

  25. Seivan wrote on 09/3/10 at 2:38 pm :

    Guess what, dips*it, this is used in production. in fact it’s used by many ruby developers around the world, the code is open source, you don’t like it, change it or don’t use it.
    It works flawlessly, no hickups, nothing.

    You seem to be missing the point with RVM. Also I’ve noticed you deleted loads of comments from people that ‘shed some light’ on the subject, why is that?

  26. Seivan wrote on 09/3/10 at 2:42 pm :

    Akoor Woot, because most people don’t have a system ruby to begin with, but have bash. Christ man, did you really even thing that shit through before spitting something so retarded out?

  27. Seivan wrote on 09/3/10 at 2:42 pm :

    Evan Dorn, you have no trouble believing the source of RVM is brittle? Did you look it up on Github or are you just listening to the author here who has clearly done shit for research.

  28. Seivan wrote on 09/3/10 at 2:49 pm :

    Also for a developer, your description of issues are quite stupid.
    “scary”? Who the fuck says scary?

    “My car/app/machine doesn’t work” <== Does that remind you of someone?

  29. Darcy Laycock wrote on 09/3/10 at 4:09 pm :

    First up, let me be 100% up front – I’ve been working on RVM for the last few months hence I’m strongly pro-RVM.

    Now, In reply to Akoor I ask:

    1) “I have looked at the code as well and this is really a piece of sh**” – What exactly makes you think it’s a piece of shit? We’d really appreciate (since Wayne seemingly is currently unable to comment on the blog to ask the same thing) what in particular you dislike and more importantly how do you think we could improve it? We’re all for making it a better tool and if you have valid suggestions we’re more than happy to hear them.

    The reasoning we “don’t they go native with a ruby script or a ant rules (or equivalent in Ruby)” is that bash is roughly equivelant of universal – it means users don’t have to have a ruby installed in the first place (which is a big thing for us) – Writing it in ruby would require an interpreter to bootstrap it. More importantly, doing it in bash lets us do the things we do on a per-shell basis such as switching rubies.

  30. Seivan wrote on 09/3/10 at 5:31 pm :

    Reminds me of a PHP developer saying “Ruby doesn’t scale” all over again, seriously where the fuck do you guys come from?

  31. Mike Bethany wrote on 09/4/10 at 3:58 am :

    I hate bad mouthing the hard work of others so I’ll just politely say, “RVM? Meh…”

    But I’ve got to point out that saying RVM is fragile is like saying a potato is really potatoey. It’s more fragile than a hymen at a high school prom and it’s pickier than a big nostriled kid in a booger flinging fight.

    ‘Nuff said.

  32. Scott Symmank wrote on 12/3/10 at 4:40 am :

    +1 rvm

    i have been using rvm for about 6 months on mac and ubuntu.

    it works great for me.

    i guess the installation script could be a *little* easier, but reading the install instructions and installing git and curl was fairly straight forward.

    i use it for continuous integration, as well as development, with gemsets, so i can switch between rails versions easily.

    if you only use one version of ruby, or aren’t comfortable with shell configurations, it might be overkill.

  33. onur wrote on 05/24/11 at 3:15 pm :

    people suggesting the use of ruby language for a tool which installs ruby?

  34. just_broken wrote on 08/18/11 at 9:36 pm :

    I do not want to use RVM in my large-scale, cloud-based, buzzword-compatible deployment environment. I am on Ubuntu. The system Ruby version is 1.9.2.0, and Ubuntu seems to feel like that is new enough. I need 1.9.2.290. Jon stated that you can install your own. I would like some tips on how to do that. I tried to install on top of what is already there using dpkg, but I ended up having to uninstall many dependencies, such as libruby1.9.1 first. Then I was able to install, but now I cannot reinstall the dependencies because they do not recognize the newer Ruby version (for some reason) and whine that they must have >= 1.9.2.0. I cannot say I am having fun. Thanks.

  35. Lucas wrote on 08/18/11 at 9:54 pm :

    Why do you need 1.9.2.290 instead of .0 ?

  36. just_broken wrote on 08/18/11 at 11:58 pm :

    It does not matter why. I need to be able to solve this problem regardless of the versions involved.

  37. Lucas wrote on 08/19/11 at 12:19 am :

    You chose to use a version of Ubuntu where the provided version of Ruby was 1.9.2.0, and to use the Ubuntu-provided packages. You want to use .290, for no good reason, apparently.
    There are several obvious solutions to your need:
    - upgrade to a newer Ubuntu version, with 1.9.2.290. I must admit that my main focus in on Debian, so I don’t know in which Ubuntu releases .290 is provided.
    - install Ruby by hand (or via RVM)

    Note that the same applies to every software package provided in Ubuntu.

    Now, if you need something from .290, and this need could be shared by other users too, solutions can be found:
    - backport the fix for the bug that annoys you, for example.
    - provide a backport of the Ruby package (but that requires work, which I’m unwilling to do if your sole justification for using .290 is “it looks shinier based on the version number”)

    One of my favorite quotes about release management is: “new release: takes old bugs out, put new bugs in.” Ruby doesn’t have a release process that prevents new bugs in new “stable” releases, since new features are also introduced. (That’s not a rant about Ruby: most projects are in that case ; GNOME is a counter-example). Therefore, it would be crazy to blindly push new Ruby stable releases to Ubuntu stable releases.

  38. just_broken wrote on 08/19/11 at 1:30 am :

    > for no good reason, apparently

    Non sequitur. Thank you for all the moralizing, but really, you are preaching to the choir. Can we please focus on the problem?

    > which I’m unwilling to do

    I am not asking anyone to “do” anything other than discuss how to solve the problem of updating Ruby on Ubuntu. If this forum or thread is not suited to that topic, I am happy to move elsewhere.

    The constraints are:

    * I cannot use a different Ubuntu distribution.
    * I need a later Ruby version than Ubuntu distributes via apt-get.
    * I would rather not use RVM.

    I have installed 1.9.2.290 via a .deb dpkg, but I had to uninstall several other packages in order to do that. Reinstalling those other packages via apt-get fails because I did not use the apt-get mechanism to update Ruby. Perhaps I can just create more .deb packages for those libraries I had to uninstall; I have not tried that. I am not in a good position to predict success; nor in a good position to know if there are better alternatives to the path I am on.

    Thank you.

  39. just_broken wrote on 08/19/11 at 6:46 am :

    I see that there is a 1.9.2.290 source package https://launchpad.net/ubuntu/+archive/primary/+files/ruby1.9.1_1.9.2.290-2.debian.tar.gz. My first reaction was Yay! But I do not understand the multiple-part control file it comes with and have no idea how to make a .deb package from it.

  40. Lucas wrote on 08/19/11 at 7:20 am :

    Which version of Ubuntu are you using?
    Would it be possible for you to *downgrade* to lucid (the latest LTS) if a backport of .290 was provided on it?

    Providing backports of Ruby for every Ubuntu release is just too much work, but I could try to provide them for LTS.

  41. just_broken wrote on 08/19/11 at 10:10 pm :

    Lucas, thanks. That is a kind offer, and greatly appreciated. I need to be able to do these things myself, though, since I doubt this is the only time I will need to do this kind of thing. I am trying to get a .deb package out of what Ubuntu posts.
    •As root, I downloaded https://launchpad.net/ubuntu/+archive/primary/+files/ruby1.9.1_1.9.2.290-2.debian.tar.gz into a new folder called “proj” and ran “tar -xzf ruby1.9.1_1.9.2.290-2.debian.tar.gz”. That created a folder called “debian” with stuff in it, including the “control” file I expect to see for a Debian package. The control file contains instructions for multiple packages. “debra” hates that, but dpkg doesn’t complain about the control file format specifically. So.
    •With the working directory as “proj”, I ran “dpkg-buildpackage -b”. That generates an empty ruby1.9.1_1.9.2.290-2.debian.tar.gz.cdbs-config_list file as a file system peer to the “debian” folder. It also generates an empty “lib” folder as peer to “debian”. Then it errors out with “chmod: cannot access `/home/ubuntu/proj/./configure’: No such file or directory”.
    This sort of sounds like dpkg wants me to start somewhere else as the working directory, but I don’t get anywhere if I do not start out with the parent of “debian” as the working directory. I’m feeling like Groundhog Day reading man dpkg over and over and over again with nothing new turning up.

  42. Lucas wrote on 08/20/11 at 10:52 am :

    Hi,

    have a look at http://www.debian.org/doc/packaging-manuals/packaging-tutorial/ for an intro to Debian packaging if you want to learn how to do that yourself.

  43. just_broken wrote on 08/23/11 at 11:19 pm :

    Thanks. I have a clearer notion now of how to deploy the .deb packages provided by Ubuntu in the general case. To answer your earlier question, Ruby’s runtime crashes intermittently during execution of our application. We have found no cause for the crash on our side. We do not use callbacks into C code; we run purely Ruby, so we are troubled that the entire runtime is going down. I count 383 bug fixes in Ruby 1.9.2p290 over p0. Reading over the description of each, few could account for what we see, but a couple are candidates. I think the more intelligent way to handle this is to use RVM to test against. If we find that 290 does in fact solve the Ruby runtime environment crashes, then I’ll worry about how to deploy in the production environment.

  44. just_broken wrote on 09/19/11 at 11:00 pm :

    From http://www.sinatrarb.com/intro: “Do not use [Ruby] 1.9.2p0, it is known to cause segmentation faults when using Sinatra.” We use Sinatra. Rake was also exploding independently of Sinatra. Ruby 1.9.2p290 solved both the Rake trouble and the Sinatra trouble. Thanks for the pointers.

  45. Agatha Rhine wrote on 09/20/11 at 4:22 pm :

    Howdy would you mind letting me know which webhost you’re utilizing? I’ve loaded your blog in 3 different web browsers and I must say this blog loads a lot faster then most. Can you recommend a good internet hosting provider at a honest price? Many thanks, I appreciate it!