RVM和rbenv如何实际工作?

时间:2012-02-22 12:00:02

标签: ruby-on-rails ruby rubygems rvm rbenv

我对RVM和rbenv的实际工作方式感兴趣。

显然,他们在不同版本的Ruby和gemsets之间进行交换,但这是如何实现的?我以为他们只是简单地更新了符号链接,但是深入研究了代码(我必须承认我对Bash的了解是肤浅的),他们似乎做的不仅仅是这个。

5 个答案:

答案 0 :(得分:237)

简短说明:rbenv通过挂钩您的环境PATH来工作。这个概念很简单,但魔鬼在于细节;完整的勺子。

首先,rbenv为所有命令创建 shims rubyirbrakegem等等已安装的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版本,然后运行该版本的相应命令。方法如下:

  1. 如果设置了RBENV_VERSION环境变量,则其值确定要使用的Ruby版本。
  2. 如果当前工作目录有.rbenv-version文件,则其内容用于设置RBENV_VERSION环境变量。
  3. 如果当前目录中没有.rbenv-version文件,rbenv会在每个父目录中搜索.rbenv-version文件,直到它到达文件系统的根目录。如果找到一个,则其内容用于设置RBENV_VERSION环境变量。
  4. 如果仍未设置RBENV_VERSION,则rbenv会尝试使用~/.rbenv/version文件的内容进行设置。
  5. 如果在任何地方都没有指定版本,rbenv假设你想要使用“系统”Ruby,即。如果rbenv不在您的路径中,将运行任何版本。
  6. (您可以使用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 Rubysetting up your environmentmanaging "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:当你改变Ruby时它会被改变。
  • rbenv:运行Ruby / gem可执行文件时它已被更改。

此外,关于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(使用rvm)或在更改目录期间自动
  • 每次执行ruby命令时,
  • 自动执行rbenv

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