Ruby-on-rails RVM 和 rbenv 实际上是如何工作的?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9394338/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 02:52:51  来源:igfitidea点击:

How do RVM and rbenv actually work?

ruby-on-railsrubyrubygemsrvmrbenv

提问by superluminary

I am interested in how RVM and rbenv actually work.

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

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.

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

回答by Sam Stephenson

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.

简短说明:rbenv 通过挂钩到您环境的PATH. 概念很简单,但细节决定成败;下面是完整的独家新闻。

First, rbenv creates shimsfor all the commands (ruby, irb, rake, gemand so on) across all your installed versions of Ruby. This process is called rehashing. Every time you install a new version of Ruby or install a gem that provides a command, run rbenv rehashto make sure any new commands are shimmed.

首先,rbenv创建垫片的所有命令(rubyirbrakegem等)跨红宝石的所有已安装的版本。这个过程称为重新散列。每次安装新版本的 Ruby 或安装提供命令的 gem 时,请运行rbenv rehash以确保任何新命令都已填充。

These shims live in a single directory (~/.rbenv/shimsby default). To use rbenv, you need only add the shims directory to the front of your PATH:

这些垫片位于单个目录中(~/.rbenv/shims默认情况下)。要使用 rbenv,您只需将 shims 目录添加到您的PATH:

export PATH="$HOME/.rbenv/shims:$PATH"

Then any time you run rubyfrom the command line, or run a script whose shebang reads #!/usr/bin/env ruby, your operating system will find ~/.rbenv/shims/rubyfirst and run it instead of any other rubyexecutable you may have installed.

然后,无论何时您从命令行运行ruby,或运行 shebang 读取的脚本#!/usr/bin/env ruby,您的操作系统都会~/.rbenv/shims/ruby首先找到并运行它,而不是ruby您可能已安装的任何其他可执行文件。

Each shim is a tiny Bash script that in turn runs rbenv exec. So with rbenv in your path, irbis equivalent to rbenv exec irb, and ruby -e "puts 42"is equivalent to rbenv exec ruby -e "puts 42".

每个 shim 都是一个微小的 Bash 脚本,它依次运行rbenv exec。因此,在您的路径中使用 rbenv 时,irb等效于rbenv exec irb,并且ruby -e "puts 42"等效于rbenv exec ruby -e "puts 42".

The rbenv execcommand figures out what version of Ruby you want to use, then runs the corresponding command for that version. Here's how:

rbenv exec命令确定您要使用的 Ruby 版本,然后运行该版本的相应命令。就是这样:

  1. If the RBENV_VERSIONenvironment variable is set, its value determines the version of Ruby to use.
  2. If the current working directory has an .rbenv-versionfile, its contents are used to set the RBENV_VERSIONenvironment variable.
  3. If there is no .rbenv-versionfile in the current directory, rbenv searches each parent directory for an .rbenv-versionfile until it hits the root of your filesystem. If one is found, its contents are used to set the RBENV_VERSIONenvironment variable.
  4. If RBENV_VERSIONis still not set, rbenv tries to set it using the contents of the ~/.rbenv/versionfile.
  5. If no version is specified anywhere, rbenv assumes you want to use the "system" Ruby—i.e. whatever version would be run if rbenv weren't in your path.
  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 不在您的路径中,则将运行任何版本。

(You can set a project-specific Ruby version with the rbenv localcommand, which creates a .rbenv-versionfile in the current directory. Similarly, the rbenv globalcommand modifies the ~/.rbenv/versionfile.)

(您可以使用该rbenv local命令设置特定于项目的 Ruby 版本,该命令会.rbenv-version在当前目录中创建一个文件。同样,该rbenv global命令会修改该~/.rbenv/version文件。)

Armed with an RBENV_VERSIONenvironment variable, rbenv adds ~/.rbenv/versions/$RBENV_VERSION/binto the front of your PATH, then execs the command and arguments passed to rbenv exec. Voila!

使用RBENV_VERSION环境变量,rbenv 添加~/.rbenv/versions/$RBENV_VERSION/bin到您的 前面PATH,然后执行传递给rbenv exec. 瞧!

For a thorough look at exactly what happens under the hood, try setting RBENV_DEBUG=1and running a Ruby command. Every Bash command that rbenv runs will be written to your terminal.

要彻底了解到底发生了什么,请尝试设置RBENV_DEBUG=1并运行 Ruby 命令。rbenv 运行的每个 Bash 命令都将写入您的终端。



Now, rbenv is just concerned with switching versions, but a thriving ecosystem of plugins will help you do everything from installing Rubyto setting up your environment, managing "gemsets"and even automating bundle exec.

现在,rbenv 只关心切换版本,但一个蓬勃发展的插件生态系统将帮助您完成从安装 Ruby设置环境管理“gemset”甚至自动化的所有工作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.

我不太确定 IRC 支持与切换 Ruby 版本有什么关系,而且 rbenv 被设计得足够简单易懂,不需要支持。但是,如果您需要帮助,只需点击几下鼠标,即可访问问题跟踪器和 Twitter。

Disclosure: I am the author of rbenv, ruby-build, and rbenv-vars.

披露:我是 rbenv、ruby-build 和 rbenv-vars 的作者。

回答by mpapis

I wrote an in-depth article: http://niczsoft.com/2011/11/what-you-should-know-about-rbenv-and-rvm/

我写了一篇深入的文章:http: //niczsoft.com/2011/11/what-you-should-know-about-rbenv-and-rvm/

The basic difference is where the shell environment is changed:

基本区别在于shell环境改变的地方:

  • RVM: it's changed when you change Ruby.
  • rbenv: it's changed when you run a Ruby/gem executable.
  • RVM:当你改变 Ruby 时它会改变。
  • rbenv:当您运行 Ruby/gem 可执行文件时,它会发生变化。

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)

此外,关于 RVM 的事情是,它涵盖的不仅仅是管理红宝石,它比任何其他工具都多得多(除了 RVM 和 rbenv 之外,还有其他工具:https://twitter.com/#! /mpapis /状态/171714447910502401)

Do not forget about instant support you get on IRC in the "#rvm" channel on the Freenode servers.

不要忘记您在 Freenode 服务器上的“#rvm”频道中获得的即时支持。

回答by superluminary

So to summarise the excellent answers above, the main practical difference between RVM and rbenv is when the version of Ruby is selected.

所以总结一下上面的优秀答案,RVM 和 rbenv 之间的主要实际区别在于选择了 Ruby 的版本。

rbenv:

rbenv:

rbenv adds a shim to the start of your path, a command with the same name as Ruby. When you type rubyat 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_versionfile to tell it which version of Ruby to delegate to.

rbenv 在路径的开头添加一个 shim,一个与 Ruby 同名的命令。当您ruby在命令行中键入时,将运行 shim(因为它也称为“ruby”并且在路径中排在第一位)。shim 查找环境变量或.rbenv_version文件以告诉它委托给哪个 Ruby 版本。

RVM:

RVM:

RVM allows you to set a version of Ruby directly by calling rvm use. In addition, it also overrides the cdsystem command. When you cdinto a folder that contains a .rvmrcfile, the code inside the .rvmrcfile is executed. This can be used to set a Ruby version, or anything else you fancy.

RVM 允许您通过调用rvm use. 此外,它还覆盖cd系统命令。当您cd进入包含.rvmrc文件的文件夹时,将.rvmrc执行文件内的代码。这可用于设置 Ruby 版本,或您喜欢的任何其他内容。

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.

当然还有其他的不同。RVM 具有开箱即用的 gemset,而 rbenv 只需要更多的黑客攻击(但并不多)。两者都是问题的功能解决方案。

回答by 0x4a6f4672

The main difference seems to be when and how ruby is switched. Ruby is switched:

主要区别似乎是何时以及如何切换 ruby。Ruby 切换:

  • for RVM manually (rvm use) or automatically during change of directories
  • for rbenv automatically each time a ruby command is executed
  • 手动(rvm 使用)或在目录更改期间自动用于 RVM
  • 每次执行 ruby​​ 命令时自动为 rbenv

RVM relies on the modified cdcommand and manual selection of Ruby by rvm 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.

RVM 依赖于cdRuby的修改命令和手动选择rvm use。rbenv 对所有基本 ruby​​ 命令使用包装器或“垫片”作为选择 ruby​​ 的默认机制。RVM 也为 gem、rake、ruby 等基本命令行工具创建包装器。例如,它们用于 CronJobs(参见http://rvm.io/integration/cron/),但它们不是切换 Ruby 版本的默认机制。

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.

因此,这两种方法都通过覆盖命令和使用包装器来“自动”选择正确的 Ruby 版本。rvm 会覆盖像 cd 这样的 shell 命令。rbenv 会覆盖所有基本的 ruby​​ 命令,例如 ruby​​、irb、rake 和 gem。

回答by Reactormonk

rvm system
env > before
rvm jruby # or whatever
env > after
diff after before

Gives you approximately:

给你大约:

< 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

And it prepends:

它预先说明:

$HOME/.rvm/gems/jruby-1.6.6/bin:$HOME/.rvm/gems/jruby-1.6.6@global/bin

to $PATH

$PATH