我感兴趣的是 RVM 和 rbenv 实际上是如何工作的。
显然,它们在不同版本的 Ruby 和 gemset 之间进行交换,但这是如何实现的呢?我原以为他们只是在更新符号链接,但在深入研究了代码之后(我必须承认,我对 Bash 的了解只是表面上的) ,他们似乎做的不止这些。
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
$PATH
我写了一篇深度文章: http://niczsoft.com/2011/11/what-you-should-know-about-rbenv-and-rvm/
基本区别在于 shell 环境在哪里发生了变化:
另外,关于 RVM 的事情是,它涵盖了很多不仅仅是管理 Ruby,它有很多比任何其他工具(除了 RVM 和 rbenv: https://twitter.com/#!/mpapis/status/171714447910502401之外还有其他工具)
不要忘记在 Freenode 服务器上的“ # rvm”通道中获得 IRC 的即时支持。
简短的解释: rbenv 通过连接到环境的 PATH来工作。这个概念很简单,但是魔鬼在于细节; 完整的独家新闻如下。
PATH
首先,rbenv 为所有已安装的 Ruby 版本中的所有命令(ruby、 irb、 rake、 gem等等)创建 垫片。这个过程称为 老调重弹。每次安装一个新版本的 Ruby 或安装一个提供命令的 gem 时,运行 rbenv rehash以确保所有新命令都被修改。
ruby
irb
rake
gem
rbenv rehash
这些垫片位于单个目录中(默认为 ~/.rbenv/shims)。要使用 rbenv,只需将 shims 目录添加到 PATH的前面:
~/.rbenv/shims
export PATH="$HOME/.rbenv/shims:$PATH"
然后,任何时候您从命令行运行 ruby,或者运行一个其 shebang 读取 #!/usr/bin/env ruby的脚本,您的操作系统将首先找到 ~/.rbenv/shims/ruby并运行它,而不是您可能已经安装的任何其他 ruby可执行文件。
#!/usr/bin/env ruby
~/.rbenv/shims/ruby
每个垫片都是一个微小的 Bash 脚本,它依次运行 rbenv exec。因此,当 rbenv 在路径中时,irb等价于 rbenv exec irb,而 ruby -e "puts 42"等价于 rbenv exec ruby -e "puts 42"。
rbenv exec
rbenv exec irb
ruby -e "puts 42"
rbenv exec ruby -e "puts 42"
rbenv exec命令确定要使用哪个版本的 Ruby,然后运行该版本的相应命令。方法如下:
.rbenv-version
RBENV_VERSION
~/.rbenv/version
(可以使用 rbenv local命令设置特定于项目的 Ruby 版本,该命令在工作目录中创建一个 .rbenv-version文件。类似地,rbenv global命令修改 ~/.rbenv/version文件。)
rbenv local
rbenv global
有了一个 RBENV_VERSION环境变量,rbenv 将 ~/.rbenv/versions/$RBENV_VERSION/bin添加到 PATH的前端,然后执行传递给 rbenv exec的命令和参数。瞧!
~/.rbenv/versions/$RBENV_VERSION/bin
要彻底了解底层到底发生了什么,请尝试设置 RBENV_DEBUG=1并运行 Ruby 命令。Rbenv 运行的每个 Bash 命令都将写入您的终端。
RBENV_DEBUG=1
现在,rbenv 只关心切换版本,但是一个蓬勃发展的插件生态系统将帮助您完成从 安装 Ruby到 建立你的环境、 管理“宝石”甚至 自动化 bundle exec的所有任务。
bundle exec
我不太确定 IRC 支持与转换 Ruby 版本有什么关系,而且 rbenv 的设计足够简单易懂,不需要支持。但是如果你需要帮助,问题跟踪器和 Twitter 只需要点击几下。
披露: 我是 rbenv,ruby-build 和 rbenv-vars 的作者。
因此,总结以上的优秀答案,RVM 和 rbenv 的主要实际区别在于选择 Ruby 版本的时间。
Rbenv:
Rbenv 在路径的开始部分添加了一个 shim,这是一个与 Ruby 同名的命令。当您在命令行中键入 ruby时,将运行垫片(因为它也被称为“ ruby”,并且在路径中排在第一位)。Shim 寻找一个环境变量或者 .rbenv_version文件来告诉它要委托给哪个版本的 Ruby。
.rbenv_version
RVM:
RVM 允许您通过调用 rvm use直接设置 Ruby 的一个版本。此外,它还覆盖了 cd系统命令。当您将 cd放入包含 .rvmrc文件的文件夹时,将执行 .rvmrc文件中的代码。这可以用来设置 Ruby 版本,或者任何你喜欢的东西。
rvm use
cd
.rvmrc
其他差异:
当然还有其他不同之处。RVM 已经开箱即用,而 rbenv 只需要更多的黑客技术(但不是很多)。两者都是问题的功能性解决方案。
主要的区别似乎是 什么时候以及如何交换 Ruby。 Ruby 被切换了:
RVM 依赖于修改后的 cd命令和 rvm use手动选择 Ruby。Rbenv 对所有基本 Ruby 命令使用 wrappers 或“ shims”作为选择 ruby 的默认机制。RVM 还为基本命令行工具(如 gem、 rake、 ruby)创建包装器。它们在 CronJobs 中使用(参见 http://rvm.io/integration/cron/) ,但它们不是切换 Ruby 版本的默认机制。
因此,这两种方法都通过覆盖命令和使用包装器来“自动”选择正确的 Ruby 版本。Rvm 重写像 cd 这样的 shell 命令。Rbenv 覆盖所有基本的 Ruby 命令,如 ruby、 irb、 rake 和 gem。