RVM 和 rbenv 实际上是如何工作的?
我对 RVM 和 rbenv 的实际工作原理感兴趣。
显然,它们在不同版本的 Ruby 和 gemset 之间进行交换,但这是如何实现的呢?我原以为他们只是简单地更新符号链接,但深入研究代码后(我必须承认我对 Bash 的了解很肤浅),他们似乎做的不仅仅是这些。
I am interested in how RVM and rbenv actually work.
Obviously they swap between different versions of Ruby and gemsets, but how is this achieved? I had assumed they were simply updating symlinks, but having delved into the code (and I must admit my knowledge of Bash is superficial) they appear to be doing more than this.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
为您提供大约:
并将:
添加到
$PATH
Gives you approximately:
And it prepends:
to
$PATH
简短说明:rbenv 通过挂钩到您的环境的
PATH
来工作。概念很简单,但细节决定成败;下面是完整的勺子。首先,rbenv 为所有命令(
ruby
、irb
、rake
、gem
创建 shims code> 等)在所有已安装的 Ruby 版本中,即~/.rbenv/versions/*/bin
中的所有文件。这个过程称为重新哈希。每次安装新版本的 Ruby 或安装提供命令的 gem 时,请运行 rbenv rehash 来确保所有新命令均已填充。这些垫片位于单个目录中(默认情况下为
~/.rbenv/shims
)。要使用 rbenv,您只需将 shims 目录添加到PATH
的前面:然后,每当您从命令行运行
ruby
时,或者运行 shebang 读取的脚本时,#!/usr/bin/env ruby
,您的操作系统将首先找到~/.rbenv/shims/ruby
并运行它,而不是任何其他ruby< /code> 您可能已安装的可执行文件。
每个 shim 都是一个微小的 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 命令修改
~/.rbenv/version
文件。)配备了
RBENV_VERSION
环境变量,rbenv 添加了将~/.rbenv/versions/$RBENV_VERSION/bin
添加到PATH
的前面,然后执行传递给rbenv exec
的命令和参数。瞧!要彻底了解幕后发生的情况,请尝试设置
RBENV_DEBUG=1
并运行 Ruby 命令。 rbenv 运行的每个 Bash 命令都将写入您的终端。现在,rbenv 只关心切换版本,但蓬勃发展的插件生态系统将帮助您完成从安装 Ruby 开始的所有事情 到设置您的环境,管理“宝石集” 甚至 自动化
捆绑执行
。我不太确定 IRC 支持与切换 Ruby 版本有什么关系,而 rbenv 的设计足够简单易懂,不需要支持。但如果您需要帮助,只需点击几下即可访问问题跟踪器和 Twitter。
披露:我是 rbenv、ruby-build 和 rbenv-vars 的作者。
Short explanation: rbenv works by hooking into your environment's
PATH
. The concept is simple, but the devil is in the details; full scoop below.First, rbenv creates shims for all the commands (
ruby
,irb
,rake
,gem
and so on) across all your installed versions of Ruby, that is for all files in~/.rbenv/versions/*/bin
. This process is called rehashing. Every time you install a new version of Ruby or install a gem that provides a command, runrbenv rehash
to make sure any new commands are shimmed.These shims live in a single directory (
~/.rbenv/shims
by default). To use rbenv, you need only add the shims directory to the front of yourPATH
:Then any time you run
ruby
from the command line, or run a script whose shebang reads#!/usr/bin/env ruby
, your operating system will find~/.rbenv/shims/ruby
first and run it instead of any otherruby
executable you may have installed.Each shim is a tiny Bash script that in turn runs
rbenv exec
. So with rbenv in your path,irb
is equivalent torbenv exec irb
, andruby -e "puts 42"
is equivalent torbenv exec ruby -e "puts 42"
.The
rbenv exec
command figures out what version of Ruby you want to use, then runs the corresponding command for that version. Here's how:RBENV_VERSION
environment variable is set, its value determines the version of Ruby to use..rbenv-version
file, its contents are used to set theRBENV_VERSION
environment variable..rbenv-version
file in the current directory, rbenv searches each parent directory for an.rbenv-version
file until it hits the root of your filesystem. If one is found, its contents are used to set theRBENV_VERSION
environment variable.RBENV_VERSION
is still not set, rbenv tries to set it using the contents of the~/.rbenv/version
file.(You can set a project-specific Ruby version with the
rbenv local
command, which creates a.rbenv-version
file in the current directory. Similarly, therbenv global
command modifies the~/.rbenv/version
file.)Armed with an
RBENV_VERSION
environment variable, rbenv adds~/.rbenv/versions/$RBENV_VERSION/bin
to the front of yourPATH
, then execs the command and arguments passed torbenv exec
. Voila!For a thorough look at exactly what happens under the hood, try setting
RBENV_DEBUG=1
and running a Ruby command. Every Bash command that rbenv runs will be written to your terminal.Now, rbenv is just concerned with switching versions, but a thriving ecosystem of plugins will help you do everything from installing Ruby to setting up your environment, managing "gemsets" and even automating
bundle exec
.I am not quite sure what IRC support has to do with switching Ruby versions, and rbenv is designed to be simple and understandable enough not to require support. But should you ever need help, the issue tracker and Twitter are just a couple of clicks away.
Disclosure: I am the author of rbenv, ruby-build, and rbenv-vars.
我写了一篇深入的文章: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 上。
I wrote an in-depth article: http://niczsoft.com/2011/11/what-you-should-know-about-rbenv-and-rvm/
The basic difference is where the shell environment is changed:
Also, the thing about RVM is, it covers a lot more then just managing Rubies, it has a lot more than any other tool (there are others apart from RVM and rbenv: https://twitter.com/#!/mpapis/status/171714447910502401)
Do not forget about instant support you get on IRC in the "#rvm" channel on the Freenode servers.
因此,总结上面的优秀答案,RVM 和 rbenv 之间的主要实际区别在于选择 Ruby 版本的时间。
rbenv:
rbenv 在路径的开头添加一个填充程序,这是一个与 Ruby 同名的命令。当您在命令行中键入 ruby 时,将运行填充程序(因为它也称为“ruby”并且位于路径的第一位)。填充程序会查找环境变量或 .rbenv_version 文件来告诉它要委托给哪个版本的 Ruby。
RVM:
RVM 允许您通过调用
rvm use
直接设置 Ruby 版本。此外,它还覆盖cd
系统命令。当您cd
进入包含.rvmrc
文件的文件夹时,将执行.rvmrc
文件内的代码。这可以用来设置 Ruby 版本,或者任何你喜欢的东西。其他差异:
当然还有其他差异。 RVM 具有开箱即用的 gemset,而 rbenv 只需要更多一点的修改(但不多)。两者都是问题的实用解决方案。
So to summarise the excellent answers above, the main practical difference between RVM and rbenv is when the version of Ruby is selected.
rbenv:
rbenv adds a shim to the start of your path, a command with the same name as Ruby. When you type
ruby
at a command line the shim is run instead (because it is also called "ruby" and comes first in the path). The shim looks for an environment variable or.rbenv_version
file to tell it which version of Ruby to delegate to.RVM:
RVM allows you to set a version of Ruby directly by calling
rvm use
. In addition, it also overrides thecd
system command. When youcd
into a folder that contains a.rvmrc
file, the code inside the.rvmrc
file is executed. This can be used to set a Ruby version, or anything else you fancy.Other differences:
There are of course other differences. RVM has gemsets out of the box, while rbenv requires just a little more hacking (but not much). Both are functional solutions to the problem.
主要区别似乎是 何时以及如何切换 ruby。 Ruby 切换:
RVM 依赖于修改后的 cd 命令并通过
手动选择 Ruby rvm 使用
。 rbenv 对所有基本 ruby 命令使用包装器或“垫片”作为选择 ruby 的默认机制。 RVM 还为基本命令行工具(如 gem、rake、ruby)创建包装器。例如,它们在 CronJobs 中使用(请参阅 http://rvm.io/integration/cron/ ),但它们不是切换 Ruby 版本的默认机制。因此,这两种方法都通过覆盖命令和使用包装器“自动”选择正确的 Ruby 版本。 rvm 会覆盖 cd 等 shell 命令。 rbenv 覆盖所有基本的 ruby 命令,例如 ruby、irb、rake 和 gem。
The main difference seems to be when and how ruby is switched. Ruby is switched:
RVM relies on the modified
cd
command and manual selection of Ruby byrvm use
. rbenv uses wrappers or "shims" for all basic ruby commands as the default mechanism to select ruby. RVM creates wrappers for basic command line tools like gem, rake, ruby, too. They are used for example in CronJobs ( see http://rvm.io/integration/cron/ ), but they are not the default mechanism to switch the Ruby version.Thus both methods select "automatically" the right Ruby version by overwriting commands and using wrappers. rvm overrides shell commands like cd. rbenv overrides all basic ruby commands such as ruby, irb, rake and gem.