RVM和rbenv如何工作?

我对RVM和rbenv如何工作感兴趣。

显然,他们在不同版本的Ruby和gemsets之间进行了切换,但是这是如何实现的呢? 我假设他们只是简单地更新符号链接,但是已经深入了解代码(我必须承认我对Bash的知识是肤浅的),但他们似乎做的不止于此。

简短的解释:rbenv通过挂钩到你的环境的PATH 。 这个概念很简单,但魔鬼在细节中; 下面全是瓢。

首先,rbenv为所有已安装的Ruby版本创build所有命令( rubyirbrakegem等)的填充。 这个过程被称为rehashing 。 每次安装新版本的Ruby或安装一个提供命令的gem时,运行rbenv rehash以确保任何新的命令都被刷新。

这些垫片生活在一个单一的目录(默认~/.rbenv/shims )。 要使用rbenv,只需要将shims目录添加到PATH的前面:

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

然后,每当你从命令行运行ruby ,或者运行一个脚本,其脚本读取#!/usr/bin/env ruby ,你的操作系统会先find~/.rbenv/shims/ruby然后运行它而不是任何其他的ruby您可能已安装的可执行文件

每个垫片是一个微小的Bash脚本,然后运行rbenv exec 。 因此,在你的pathrbenv, irb相当于rbenv exec irbruby -e "puts 42"相当于rbenv exec ruby -e "puts 42"

rbenv exec命令rbenv exec您要使用的Ruby版本,然后为该版本运行相应的命令。 就是这样:

  1. 如果设置了RBENV_VERSION环境variables,则其值将决定要使用的Ruby版本。
  2. 如果当前工作目录有一个.rbenv-version文件,则其内容用于设置RBENV_VERSION环境variables。
  3. 如果当前目录中没有.rbenv-version文件,则rbenv会在每个父目录中search一个.rbenv-version文件,直到它到达文件系统的根目录。 如果find其中的一个,则其内容用于设置RBENV_VERSION环境variables。
  4. 如果RBENV_VERSION尚未设置,rbenv会尝试使用~/.rbenv/version文件的内容进行设置。
  5. 如果没有在任何地方指定版本,rbenv假定你想要使用“系统”的Ruby – 即任何版本将运行,如果rbenv不在你的path。

(你可以使用rbenv local命令设置项目特定的Ruby版本,在当前目录下创build一个.rbenv-version文件,类似的, rbenv global命令修改~/.rbenv/version文件。

使用RBENV_VERSION环境variables,rbenv将~/.rbenv/versions/$RBENV_VERSION/binPATH的前面,然后执行传递给rbenv exec的命令和参数。 瞧!

要彻底了解RBENV_DEBUG=1发生了什么,尝试设置RBENV_DEBUG=1并运行Ruby命令。 rbenv运行的每个Bash命令将被写入您的terminal。


现在,rbenv只关心切换版本,但是繁荣的插件生态系统将帮助您从安装Ruby到设置环境 , pipe理“gemset”甚至自动bundle exec

我不太清楚IRC支持与切换Ruby版本有什么关系,rbenv的devise简单易懂,不需要支持。 但是,如果您需要帮助,问题跟踪器和Twitter只需要几个点击即可。

披露:我是rbenv,ruby-build和rbenv-vars的作者。

我写了一篇深入的文章: http : //niczsoft.com/2011/11/what-you-should-know-about-rbenv-and-rvm/

基本的区别在于shell环境的改变:

  • RVM:当你改变Ruby的时候就改变了。
  • rbenv:当你运行一个Ruby / gem可执行文件时,它会被改变。

另外,关于RVM的事情是,它涵盖了更多的只是pipe理Rubies,它比其他任何工具都多(除了RVM和rbenv之外,还有其他一些工具: https ://twitter.com/#! / mpapis /状态/ 171714447910502401 )

不要忘记在Freenode服务器的“#rvm”频道上获得对IRC的即时支持。

因此,为了总结上面的优秀答案,RVM和rbenv之间的主要实际区别在于select了Ruby的版本。

rbenv:

rbenv在你的path开始添加了一个垫片,一个和Ruby相同的命令。 当你在命令行键入ruby时,shim会运行(因为它也被称为“ruby”,并且首先在path中)。 shim查找一个环境variables或.rbenv_version文件来告诉它要委派哪个版本的Ruby。

RVM:

RVM允许你直接调用rvm use来设置Ruby的一个版本。 另外,它也覆盖了cd系统命令。 当您进入包含.rvmrc文件的文件夹时,将执行.rvmrc文件中的代码。 这可以用来设置一个Ruby版本,或者任何你喜欢的东西。

其他区别:

当然还有其他的不同之处。 RVM已经开箱了,而rbenv只需要更多的黑客(但不是太多)。 两者都是解决问题的function。

 rvm system env > before rvm jruby # or whatever env > after diff after before 

大致给你:

 < GEM_HOME=$HOME/.gem/ruby/1.9.1 --- > GEM_HOME=$HOME/.rvm/gems/jruby-1.6.6 < GEM_PATH=$HOME/.gem/ruby/1.9.1 --- > GEM_PATH=$HOME/.rvm/gems/jruby-1.6.6:$HOME/.rvm/gems/jruby-1.6.6@global *bunch of rvm_* > MY_RUBY_HOME=$HOME/.rvm/rubies/jruby-1.6.6 > RUBY_VERSION=jruby-1.6.6 > IRBRC=$HOME/.rvm/rubies/jruby-1.6.6/.irbrc 

它预先说明:

 $HOME/.rvm/gems/jruby-1.6.6/bin:$HOME/.rvm/gems/jruby-1.6.6@global/bin 

$PATH

主要的区别似乎是什么时候以及如何ruby切换 。 Ruby被切换:

  • 对于RVM手动(rvm使用)或在更改目录期间自动
  • 对于rbenv自动每次执行ruby命令

RVM依靠修改后的cd命令和rvm use手动selectRuby。 rbenv使用所有基本ruby命令的包装或“填充”作为selectruby的默认机制。 RVM为gem,rake,ruby等基本的命令行工具创build了包装器。 它们用于CronJobs(请参阅http://rvm.io/integration/cron/ ),但它们不是用于切换Ruby版本的默认机制。

因此,这两种方法都通过覆盖命令和使用包装来“自动”select正确的Ruby版本。 rvm覆盖shell命令,如cd。 rbenv覆盖了所有基本的ruby命令,比如ruby,irb,rake和gem。