How Do Rvm and Rbenv Actually Work

How do RVM and rbenv actually work?

Short explanation: rbenv works by hooking into your environment's PATH. The concept is simple, but the devil is in the details; full scoop below.

First, rbenv creates shims for all the commands (ruby, irb, rake, gem and so on) across all your installed versions of Ruby. This process is called rehashing. Every time you install a new version of Ruby or install a gem that provides a command, run rbenv rehash to make sure any new commands are shimmed.

These shims live in a single directory (~/.rbenv/shims by default). To use rbenv, you need only add the shims directory to the front of your PATH:

export PATH="$HOME/.rbenv/shims:$PATH"

Then any time you run ruby from the command line, or run a script whose shebang reads #!/usr/bin/env ruby, your operating system will find ~/.rbenv/shims/ruby first and run it instead of any other ruby executable you may have installed.

Each shim is a tiny Bash script that in turn runs rbenv exec. So with rbenv in your path, irb is equivalent to rbenv exec irb, and ruby -e "puts 42" is equivalent to rbenv exec ruby -e "puts 42".

The rbenv exec command figures out what version of Ruby you want to use, then runs the corresponding command for that version. Here's how:

  1. If the RBENV_VERSION environment variable is set, its value determines the version of Ruby to use.
  2. If the current working directory has an .rbenv-version file, its contents are used to set the RBENV_VERSION environment variable.
  3. If there is no .rbenv-version file in the current directory, rbenv searches each parent directory for an .rbenv-version file until it hits the root of your filesystem. If one is found, its contents are used to set the RBENV_VERSION environment variable.
  4. If RBENV_VERSION is still not set, rbenv tries to set it using the contents of the ~/.rbenv/version file.
  5. If no version is specified anywhere, rbenv assumes you want to use the "system" Ruby—i.e. whatever version would be run if rbenv weren't in your path.

(You can set a project-specific Ruby version with the rbenv local command, which creates a .rbenv-version file in the current directory. Similarly, the rbenv global command modifies the ~/.rbenv/version file.)

Armed with an RBENV_VERSION environment variable, rbenv adds ~/.rbenv/versions/$RBENV_VERSION/bin to the front of your PATH, then execs the command and arguments passed to rbenv exec. Voila!

For a thorough look at exactly what happens under the hood, try setting RBENV_DEBUG=1 and running a Ruby command. Every Bash command that rbenv runs will be written to your terminal.


Now, rbenv is just concerned with switching versions, but a thriving ecosystem of plugins will help you do everything from installing Ruby to setting up your environment, managing "gemsets" and even automating bundle exec.

I am not quite sure what IRC support has to do with switching Ruby versions, and rbenv is designed to be simple and understandable enough not to require support. But should you ever need help, the issue tracker and Twitter are just a couple of clicks away.

Disclosure: I am the author of rbenv, ruby-build, and rbenv-vars.

What do rvm and rbenv do under the hood to install Ruby?

Rbenv and rvm manages multiple versions of Ruby. The question you link to describes how both of those tools do that (some people are of the opinion that rvm's integration with your shell is too heavyweight/magical ) . The ability to have multiple versions of Ruby coexisting nicely is a pretty big win. Historically there have been some disruptive releases (eg 1.8.7, 1.9.2) and so being able to migrate your development piecemeal or easily work on legacy projects has been very advantageous.

The Ruby install process isn't that complicated at its heart - it's pretty much the usual download the source ./configure && make && sudo make install (RVM also has support for prebuilt Rubies). You can however tie yourself in knots (especially as a newcomer to Ruby)

While some missing dependencies will just cause the Ruby build process to fail, others will just stop specific Ruby extensions from compiling (openssl or readline). You think you have a fully functioning Ruby until you try to run some code that uses those extensions. Others are even more subtle, for example if libyaml is not available then some versions of Ruby fall back to using syck as the YAML library instead of the more modern psych, with subtle differences.

RVM just makes it very easy, compiling nearly any Ruby interpreter, version or patch level (jRuby, Rubinius, MRI etc.), with or without extra patches is only ever a single invocation. It's not doing anything very magical but it does remove a lot of friction.

What are the differences between rbenv, rvm, and chruby?

There's three main options available today:

  • rvm which is the most established, but also the most intrusive in terms of shell modifications.
  • rbenv which is lower impact, and still works as well.
  • chruby which purports to be even lighter than rbenv.

Personally I prefer rbenv because it works well with Homebrew and doesn't mangle the shell environment as much, but tend to use rvm on servers where that doesn't matter because they're set up for a very specific purpose.

Need help switching from RVM to RBENV

My RVM implode script is here -- you can edit is as you like.

https://github.com/sixarm/rvm-implode-systemwide-danger

The script does RVM implode, systemwide, and is dangerous. The script will seek and destroy RVM installations, rvm gems, .rvmrc files, and then search your entire system for lingering files and and references.

Suggestions and pull requests are very welcome. I'm the author.

The entire script is copy/paste below for reference. The link above is probably better because it will have any updates, changes, improvements, etc.

#!/bin/sh
#
# Uninstall RVM (Ruby Version Manager) systemwide:
# THIS IS DANGEROUS.
#
# This script tries to eliminate RVM everywhere on the system,
# by doing these steps:
#
# * Run `rvm implode`
# * Delete all known RVM-related files everywhere on the system.
# * Delete all users' home directory `.rvm` directories and `.rvmrc` files.
# * Uninstall all known RVM gems.
# * Search the system for potential lingering items and print them.
#
# ## Use at your own risk
#
# This script is not advanced:
#
# * it does not do any error checking
# * it does not ensure anything worked
# * it does not guarantee success
#
# If it doesn't work for you, please let us know and we'll improve it.
#
# We welcome feedback, patches, and pull requests.
#
# ## Warnings
#
# Some of the script lines may report missing directories.
#
# For example, a Mac system typically has a /Users/ directory,
# whereas a Linux system typically has a /home/ directory.
# You can delete the lines that you don't need, if you like.
#
# If rvm implode gives errors like this loop:
#
# line 72: /usr/local/rvm/scripts/rvm: No such file or directory
#
# then the rvm setup is bonked and we can delete the rvm script
# by hand then run this script again; rvm implode won't work,
# but the rest of the script will do a decent job of deleting
# any lingering rvm files and reporting any remainders.
#
# Command: rvm-implode-systemwide-danger
# Version: 2.0.0
# Created: 2011-08-22
# Updated: 2015-01-25
# License: GPL
# Contact: Joel Parker Henderson (joel@joelparkerhenderson.com)
##
set -euf
out () { printf %s\\n "$*" ; }

out "rvm implode"
rvm implode

out "remove rvm files from system-wide areas"
sudo rm -rf /usr/local/bin/rvm
sudo rm -rf /usr/local/rvm
sudo rm -rf /etc/rvmrc
sudo rm -rf /etc/profile.d/rvm.sh

out "remove rvm files from all likely user areas"
sudo rm -rf /home/*/.rvm
sudo rm -rf /home/*/.rvmrc
sudo rm -rf /Users/*/.rvm
sudo rm -rf /Users/*/.rvmrc
sudo rm -rf $HOME/.rvm
sudo rm -rf $HOME/.rvmrc
sudo rm -rf $(dirname $HOME)/*/.rvm
sudo rm -rf $(dirname $HOME)/*/.rvmrc

out "uninstall rvm gem as current user and with sudo"
gem uninstall -a -q rvm
sudo gem uninstall -a -q rvm

out "delete rvm group"
sudo /usr/sbin/groupdel rvm

out "try to find any remaining .rvmrc files, in case you want to delete them"
sudo find -L / -name .rvmrc

out "try to find rvm text in configuration files, in case you want to edit thme"
sudo find -L / -type f | grep "\(bash_login\|bash_profile\|bashrc\|profile\|zshenv\|zshrc\|zlogin\|zlogout\|zprofile\)$" | xargs -I{} grep -Iil "rvm" {}

Should I Use rbenv or RVM for RubyMine

sudo is just a command that executes the command following it as root. This results in files created by those commands being owned by root, and being uneditable and undeletable by your user account.

rvm vs. rbenv is a matter of personal preference -- my preference is rvm. I find it very easy to use and rich in functionality. You don't need to install it using sudo -- in fact, I prefer not to. It will install everything in a ~/.rvm directory, and requires some minor modification to your startup scripts, which it can usually do automatically as part of the installation. Google install rvm for clear instructions about how to install it.



Related Topics



Leave a reply



Submit