问题描述
我对 RVM 和 rbenv 的实际工作方式很感兴趣.
I am interested in how RVM and rbenv actually work.
显然,它们在不同版本的 Ruby 和 gemset 之间进行交换,但这是如何实现的呢?我原以为他们只是在更新符号链接,但在深入研究代码后(我必须承认我对 Bash 的了解是肤浅的),他们似乎做的不止这些.
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.
推荐答案
简短说明:rbenv 通过挂钩到环境的 PATH
来工作.概念很简单,但魔鬼在细节中;下面是完整的独家新闻.
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 为所有命令(ruby
、irb
、rake
、 创建 shimsgem
等)在所有已安装的 Ruby 版本中.这个过程称为重新散列.每次安装新版本的 Ruby 或安装提供命令的 gem 时,运行 rbenv rehash
以确保所有新命令都已填充.
First, rbenv creates shims for all the commands (ruby
, irb
, rake
, gem
and 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 rehash
to make sure any new commands are shimmed.
这些 shim 位于一个目录中(默认为 ~/.rbenv/shims
).要使用 rbenv,您只需将 shims 目录添加到 PATH
的前面:
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 your PATH
:
export PATH="$HOME/.rbenv/shims:$PATH"
然后,任何时候你从命令行运行 ruby
,或者运行 shebang 读取 #!/usr/bin/env ruby
的脚本,你的操作系统都会找到~/.rbenv/shims/ruby
首先运行它而不是您可能安装的任何其他 ruby
可执行文件.
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 other ruby
executable you may have installed.
每个 shim 都是一个小型 Bash 脚本,依次运行 rbenv exec
.所以在你的路径中使用 rbenv,irb
相当于 rbenv exec irb
,ruby -e "puts 42"
相当于 rbenv exec ruby -e "puts 42"
.
Each shim is a tiny Bash script that in turn runs rbenv exec
. So with rbenv in your path, irb
is equivalent to rbenv exec irb
, and ruby -e "puts 42"
is equivalent to rbenv exec ruby -e "puts 42"
.
rbenv exec
命令确定您要使用的 Ruby 版本,然后针对该版本运行相应的命令.方法如下:
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
环境变量,则其值决定了要使用的 Ruby 版本. - 如果当前工作目录有
.rbenv-version
文件,则其内容用于设置RBENV_VERSION
环境变量. - 如果当前目录中没有
.rbenv-version
文件,rbenv 会在每个父目录中搜索.rbenv-version
文件,直到找到您的根目录文件系统.如果找到,则其内容用于设置RBENV_VERSION
环境变量. - 如果
RBENV_VERSION
仍未设置,rbenv 会尝试使用~/.rbenv/version
文件的内容进行设置. - 如果在任何地方都没有指定版本,rbenv 会假定您要使用系统"Ruby——即如果 rbenv 不在您的路径中,将运行任何版本.
- If the
RBENV_VERSION
environment variable is set, its value determines the version of Ruby to use. - If the current working directory has an
.rbenv-version
file, its contents are used to set theRBENV_VERSION
environment variable. - If there is no
.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. - If
RBENV_VERSION
is still not set, rbenv tries to set it using the contents of the~/.rbenv/version
file. - 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.
(您可以使用 rbenv local
命令设置项目特定的 Ruby 版本,该命令会在当前目录中创建一个 .rbenv-version
文件.同样,rbenv global
命令修改 ~/.rbenv/version
文件.)
(You can set a project-specific Ruby version with the rbenv local
command, which creates a .rbenv-version
file in the current directory. Similarly, the rbenv global
command modifies the ~/.rbenv/version
file.)
使用 RBENV_VERSION
环境变量,rbenv 将 ~/.rbenv/versions/$RBENV_VERSION/bin
添加到您的 PATH
前面, 然后执行传递给 rbenv exec
的命令和参数.瞧!
Armed with an RBENV_VERSION
environment variable, rbenv adds ~/.rbenv/versions/$RBENV_VERSION/bin
to the front of your PATH
, then execs the command and arguments passed to rbenv exec
. Voila!
要彻底了解幕后究竟发生了什么,请尝试设置 RBENV_DEBUG=1
并运行 Ruby 命令.rbenv 运行的每个 Bash 命令都将写入您的终端.
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.
现在,rbenv 只关心切换版本,但蓬勃发展的插件生态系统将帮助您完成所有工作,从 安装 Ruby 到 设置你的环境, 管理 "gemset" 甚至 自动化 bundle exec
.
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
.
我不太确定 IRC 支持与切换 Ruby 版本有什么关系,而 rbenv 被设计为简单易懂,不需要支持.但是,如果您需要帮助,只需单击几下即可获得问题跟踪器和 Twitter.
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.
披露:我是 rbenv、ruby-build 和 rbenv-vars 的作者.
这篇关于RVM 和 rbenv 是如何工作的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!