我对RVM和rbenv的实际工作方式感兴趣。
显然,他们在不同版本的Ruby和gemsets之间进行交换,但这是如何实现的?我以为他们只是简单地更新了符号链接,但是深入研究了代码(我必须承认我对Bash的了解是肤浅的),他们似乎做的不仅仅是这个。
答案 0 :(得分:237)
简短说明:rbenv通过挂钩您的环境PATH
来工作。这个概念很简单,但魔鬼在于细节;完整的勺子。
首先,rbenv为所有命令创建 shims (ruby
,irb
,rake
,gem
等等已安装的Ruby版本。此过程称为 rehashing 。每次安装新版本的Ruby或安装提供命令的gem时,请运行rbenv rehash
以确保所有新命令都已填充。
这些填充程序位于单个目录中(默认为~/.rbenv/shims
)。要使用rbenv,您只需将填充程序目录添加到PATH
:
export PATH="$HOME/.rbenv/shims:$PATH"
然后,只要您从命令行运行ruby
,或者运行shebang读取#!/usr/bin/env ruby
的脚本,您的操作系统将首先找到~/.rbenv/shims/ruby
并运行它而不是任何其他ruby
{1}}您可能安装的可执行文件。
每个垫片都是一个小的Bash脚本,而后者又运行rbenv exec
。因此,在路径中使用rbenv时,irb
相当于rbenv exec irb
,而ruby -e "puts 42"
相当于rbenv exec ruby -e "puts 42"
。
rbenv exec
命令确定要使用的Ruby版本,然后运行该版本的相应命令。方法如下:
RBENV_VERSION
环境变量,则其值确定要使用的Ruby版本。.rbenv-version
文件,则其内容用于设置RBENV_VERSION
环境变量。.rbenv-version
文件,rbenv会在每个父目录中搜索.rbenv-version
文件,直到它到达文件系统的根目录。如果找到一个,则其内容用于设置RBENV_VERSION
环境变量。RBENV_VERSION
,则rbenv会尝试使用~/.rbenv/version
文件的内容进行设置。(您可以使用rbenv local
命令设置特定于项目的Ruby版本,该命令在当前目录中创建.rbenv-version
文件。同样,rbenv global
命令修改{{1}文件。)
使用~/.rbenv/version
环境变量,rbenv将RBENV_VERSION
添加到~/.rbenv/versions/$RBENV_VERSION/bin
的前面,然后执行传递给PATH
的命令和参数。瞧!
要彻底了解幕后发生的事情,请尝试设置rbenv exec
并运行Ruby命令。 rbenv运行的每个Bash命令都将写入终端。
现在,rbenv只关注切换版本,但繁荣的插件生态系统将帮助您完成从installing Ruby到setting up your environment,managing "gemsets"甚至automating bundle exec
的所有操作。
我不太清楚IRC支持与切换Ruby版本有什么关系,而rbenv的设计简单易懂,不需要支持。但是,如果您需要帮助,问题跟踪器和Twitter只需点击几下即可。
披露:我是rbenv,ruby-build和rbenv-vars的作者。
答案 1 :(得分:18)
我写了一篇深度文章:http://niczsoft.com/2011/11/what-you-should-know-about-rbenv-and-rvm/
基本区别在于shell环境发生了变化:
此外,关于RVM的事情是,它比管理Rubies要多得多,它比其他任何工具都要多得多(除了RVM和rbenv之外还有其他工具:https://twitter.com/#!/mpapis/status/171714447910502401)
不要忘记在Freenode服务器上的“#rvm”频道中获得IRC的即时支持。
答案 2 :(得分:15)
总结上面的优秀答案,RVM和rbenv之间的主要实际区别在于选择了Ruby的版本。
<强> rbenv:强>
rbenv在路径的开头添加了一个垫片,这是一个与Ruby同名的命令。当您在命令行键入ruby
时,将运行填充程序(因为它也称为“ruby”并且在路径中位于第一位)。垫片会查找环境变量或.rbenv_version
文件,以告诉它要委派给哪个版本的Ruby。
<强> RVM:强>
RVM允许您通过调用rvm use
直接设置Ruby版本。此外,它还会覆盖cd
系统命令。当您cd
进入包含.rvmrc
文件的文件夹时,将执行.rvmrc
文件中的代码。这可用于设置Ruby版本或您想要的任何其他内容。
其他差异:
当然还有其他差异。 RVM开箱即用,而rbenv只需要更多的黑客攻击(但不多)。两者都是问题的功能性解决方案。
答案 3 :(得分:6)
主要区别似乎是when and how ruby is switched。 Ruby已切换:
RVM依赖于修改后的cd
命令和rvm use
手动选择Ruby。 rbenv为所有基本ruby命令使用包装器或“填充程序”作为选择ruby的默认机制。 RVM也为gem,rake,ruby等基本命令行工具创建包装器。例如,它们用在CronJobs中(参见http://rvm.io/integration/cron/),但它们不是切换Ruby版本的默认机制。
因此,两种方法都通过覆盖命令和使用包装器来“自动”选择正确的Ruby版本。 rvm覆盖像cd这样的shell命令。 rbenv会覆盖所有基本的ruby命令,例如ruby,irb,rake和gem。
答案 4 :(得分:5)
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