RVM和rbenv如何工作?
我对RVM和rbenv如何工作感兴趣。
显然,他们在不同版本的Ruby和gemsets之间进行了切换,但是这是如何实现的呢? 我假设他们只是简单地更新符号链接,但是已经深入了解代码(我必须承认我对Bash的知识是肤浅的),但他们似乎做的不止于此。
简短的解释:rbenv通过挂钩到你的环境的PATH
。 这个概念很简单,但魔鬼在细节中; 下面全是瓢。
首先,rbenv为所有已安装的Ruby版本创build所有命令( ruby
, irb
, rake
, gem
等)的填充。 这个过程被称为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 irb
, ruby -e "puts 42"
相当于rbenv exec ruby -e "puts 42"
。
rbenv exec
命令rbenv exec
您要使用的Ruby版本,然后为该版本运行相应的命令。 就是这样:
- 如果设置了
RBENV_VERSION
环境variables,则其值将决定要使用的Ruby版本。 - 如果当前工作目录有一个
.rbenv-version
文件,则其内容用于设置RBENV_VERSION
环境variables。 - 如果当前目录中没有
.rbenv-version
文件,则rbenv会在每个父目录中search一个.rbenv-version
文件,直到它到达文件系统的根目录。 如果find其中的一个,则其内容用于设置RBENV_VERSION
环境variables。 - 如果
RBENV_VERSION
尚未设置,rbenv会尝试使用~/.rbenv/version
文件的内容进行设置。 - 如果没有在任何地方指定版本,rbenv假定你想要使用“系统”的Ruby – 即任何版本将运行,如果rbenv不在你的path。
(你可以使用rbenv local
命令设置项目特定的Ruby版本,在当前目录下创build一个.rbenv-version
文件,类似的, rbenv global
命令修改~/.rbenv/version
文件。
使用RBENV_VERSION
环境variables,rbenv将~/.rbenv/versions/$RBENV_VERSION/bin
到PATH
的前面,然后执行传递给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。