Ruby 更简单灵活地管理 Ruby 版本

darkbaby123 · 2015年11月05日 · 最后由 billy 回复于 2015年11月08日 · 9644 次阅读

原文贴在 SegmentFault ,有兴趣的可以过去瞄哈。

概述

这篇文章教你怎么用 ruby-install 和 chruby 这两个工具来管理和切换 Ruby 版本,相对 RVM 和 rbenv 来说这是一个更加轻量级且绿色环保的组合。

为什么不用 RVM 或者 rbenv

首先说明一点,切换 ruby-install 和 chruby 并不是因为它们有什么独一无二的特性。它们能做到的事情 RVM 和 rbenv 都可以做到。如果你用着现有的工具感觉良好,也没有尝鲜的打算,完全可以不换。

那我为什么要换?对我而言有几个原因:

  1. 我想用一个 Homebrew 可以管理和升级的工具。
  2. 最好是工具不升级也可以安装最新的 Ruby 版本。
  3. 功能和实现都很简单。因为我只需要安装和切换不同的 Ruby 版本,不需要其他的功能。

关于最后一点我想多说几句,最近一年我对软件的看法有些改变。对我而言好的软件最重要的是 简单够用 。我不想为用不到的功能买单,它们可能增加潜在的复杂度和维护成本。我也不喜欢软件为了达到功能做了太多 hack,这会影响它跟其他软件组合使用的轻松程度,进而影响未来替换它的轻松程度。我以前一直在用 RVM,这次本来准备换成 rbenv,但当我看了 rbenv 对 shim 的大堆解释 后觉得这不是我想要的理想替代品。正好前几天同事推荐 chruby,@Hooopo这篇文章 也让我觉得这应该是个不错的玩意(希望没拼错那几个 o),于是就果断删了 RVM 切换过去了。过程比我想得还要轻松许多。

使用 ruby-install & chruby

这其实是两个工具,ruby-install 只负责下载、编译和安装多个 Ruby 版本,chruby 负责切换。它们的名字就是命令行的名字,所以你需要用到两个命令(但都非常简单)。你可以点它们的名字去 Github 看 README.md。下面我只提供基本用法的例子(用的 Homebrew):

安装 ruby-install

brew install ruby-install

安装指定 Ruby 版本

ruby-install ruby 2.2.3

安装 chruby

brew install chruby

切换 Ruby 版本

chruby ruby-2.2.3

然后在 .bashrc 或者 .bash_profile 里加入脚本(具体路径最好照官方说明来)。第一个脚本加载 chruby,第二个脚本控制自动切换(按 .ruby-version 文件)。

source /usr/local/opt/chruby/share/chruby/chruby.sh
source /usr/local/opt/chruby/share/chruby/auto.sh

关于默认 Ruby 版本,chruby 没有这种命令,但我们需要的只是“在适当的时候让 chruby 自动切换到指定版本” 。chruby 会从当前目录向上一层层地找 .ruby-version 文件,所以你只要把默认 Ruby 版本写在 ~/.ruby-version 里就可以了,以此类推,如果需要在任何目录下都能切换到默认版本,你可以考虑 /.ruby-version,我没这个需求,就没有尝试。

在命令提示符里显示 Ruby 版本

这几乎是 Ruby 开发的“刚需”了。我是自己写了个简单的脚本做到这点的。原理很简单,用 ruby --version 显示当前使用的版本,截取版本号再插入提示符就行了(修改 PS1 变量)。以我的 bash 举例子:

# 如果当前目录有 Gemfile 就显示 Ruby 版本;如果有 package.json 就显示 Node.js 版本,否则什么都不显示。
# 结果大概会显示成 [email protected] 或者 [email protected]
function env_version {
  if [ -e ./Gemfile ]; then
    # ruby 2.2.2p95 (2015-04-13..) -> 2.2.2p95 -> 2.2.2
    echo "ruby@$(ruby --version | awk '{print $2}' | awk -F'p' '{print $1}') ";
  elif [ -e ./package.json ]; then
    # v4.2.1 -> 4.2.1
    echo "node@$(node -v | awk -F'v' '{print $2}') ";
  else
    echo "";
  fi
}

# 用 $() 嵌入 env_version 的结果
PS1="$(env_version)"

我自己用的 PS1 变量显示了路径,Ruby/Node.js 版本,和 Git 分支名。感兴趣的可以参考 我的 dotfile,最终效果大概如此:

~/workspace/my-project [email protected] [staging] $

最后附带一点,如果不想频繁地敲 bundle exec xxx,可以看看文末链接的 Automating bundle exec 。这是一个简单的 alias 脚本。不过我在同事的 rbenv 环境上没试成功,不确定是不是受 rbenv 的 shim 影响。如果是的话,这也侧面证明了 less hack 的好处。

参考链接

Install Ruby The "Postmodern" Way Programmer's guide to choosing a Ruby version manager Automating bundle exec

源码安装才是最好的😄

@qilinzou 嗯,我也喜欢源码编译安装。 ruby-install 就是源码安装的,并且可以看到全过程。其实我觉得“安装”这个词不大恰当,因为 ruby-install 就是自动帮你下载,编译,然后放到指定的目录去(~/.rubies/ruby-x.x.x)。它省去的是“手动找下载地址,然后敲命令编译”的功夫。

请教 chruby 的 gems 也是按版本分开放的么?

@billy 是的,但 chruby 安装 gem 的路径和 ruby-install 安装的 Ruby 路径没有关系,举个例子,对于 ruby 2.2.2:

  • ruby-install 把 ruby 安装在 ~/.rubies/ruby-2.2.2 下面。
  • chruby 切换到 ruby-2.2.2 后安装 gem 会安装在 ~/.gem/ruby/2.2.2 下面。

附上我本地的 $GEM_HOME$GEM_PATH 也许更能说明问题。

~ $ echo $GEM_HOME
/Users/david/.gem/ruby/2.2.2
~ $ echo $GEM_PATH
/Users/david/.gem/ruby/2.2.2:/Users/david/.rubies/ruby-2.2.2/lib/ruby/gems/2.2.0

@darkbaby123 明白了,谢谢!这个挺好,看着很简便。现在用着 rvm, 下次要折腾就试试它了 😄

需要 登录 后方可回复, 如果你还没有账号请 注册新账号