Как на самом деле работают RVM и rbenv?

130

Мне интересно, как работают RVM и rbenv.

Очевидно, они меняются между разными версиями Ruby и gemset, но как это достигается? Я предположил, что они просто обновляют символические ссылки, но вникая в код (и я должен признать, что мои знания Bash являются поверхностными), они, похоже, делают больше, чем это.

Теги:
rubygems
rvm
rbenv

5 ответов

213
Лучший ответ

Краткое объяснение: rbenv работает, подключаясь к вашей среде PATH. Концепция проста, но дьявол находится в деталях; полный совок ниже.

Во-первых, rbenv создает прокладки для всех команд (ruby, irb, rake, gem и т.д.) во всех ваших установленных версиях Ruby. Этот процесс называется rehashing. Каждый раз, когда вы устанавливаете новую версию Ruby или устанавливаете драгоценный камень, который предоставляет команду, запустите rbenv rehash, чтобы убедиться, что все новые команды отрегулированы.

Эти прокладки живут в одном каталоге (~/.rbenv/shims по умолчанию). Чтобы использовать rbenv, вам нужно только добавить каталог прокладок в начало вашего PATH:

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

Затем в любое время, когда вы запускаете ruby из командной строки или запускаете script, чья shebang читает #!/usr/bin/env ruby, ваша операционная система сначала найдет ~/.rbenv/shims/ruby и запустит ее вместо любого другого исполняемого файла ruby возможно, установлены.

Каждая прокладка представляет собой крошечный Bash script, который, в свою очередь, запускает 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 предполагает, что вы хотите использовать "систему" ​​Ruby-i.e. любая версия будет запущена, если rbenv не было на вашем пути.

(Вы можете установить версию Ruby для конкретного проекта с помощью команды rbenv local, которая создает в текущем каталоге файл .rbenv-version. Аналогично, команда rbenv global изменяет файл ~/.rbenv/version.)

Вооруженный переменной окружения RBENV_VERSION, rbenv добавляет ~/.rbenv/versions/$RBENV_VERSION/bin в начало вашего PATH, затем выполняет команду и аргументы, переданные в rbenv exec. Вуаля!

Подробно посмотрите, что происходит под капотом, попробуйте установить RBENV_DEBUG=1 и запустить команду Ruby. Каждая команда Bash, запускаемая rbenv, будет записана на ваш терминал.


Теперь rbenv просто касается переключения версий, но процветающая экосистема плагинов поможет вам сделать все, начиная с установки Ruby до настройка среды, управление "gemsets" и даже автоматизация bundle exec.

Я не совсем уверен, что поддержка IRC связана с переключением версий Ruby, и rbenv разработан, чтобы быть простым и понятным, чтобы не требовать поддержки. Но если вам когда-нибудь понадобится помощь, трекер и Twitter будут всего в нескольких кликах.

Раскрытие информации: Я являюсь автором rbenv, ruby-build и rbenv-vars.

  • 14
    Спасибо, что нашли время, чтобы дать такой отличный ответ.
  • 2
    Вау, спасибо за такое понятное и понятное объяснение. Прирожденный учитель.
Показать ещё 4 комментария
18

Я написал углубленную статью: http://niczsoft.com/2011/11/what-you-should-know-about-rbenv-and-rvm/

Основное отличие заключается в том, что среда оболочки изменяется:

  • RVM: он изменился при изменении Ruby.
  • rbenv: он изменился при запуске исполняемого файла Ruby/gem.

Кроме того, дело в RVM заключается в том, что он охватывает намного больше, чем просто управление Rubies, у него намного больше, чем у любого другого инструмента (кроме RVM и rbenv есть другие: https://twitter.com/#!/mpapis/status/171714447910502401)

Не забывайте о мгновенной поддержке, которую вы получаете на IRC в канале "#rvm" на серверах Freenode.

  • 1
    Спасибо, действительно здорово, что люди из обоих сообществ принимают участие.
13

Итак, чтобы обобщить превосходные ответы выше, основная практическая разница между RVM и rbenv заключается в том, когда выбрана версия Ruby.

rbenv:

rbenv добавляет прокладку к началу вашего пути, команду с тем же именем, что и Ruby. Когда вы введете ruby в командной строке, вместо этого выполняется прокладка (потому что она также называется "ruby" и на первом идет по пути). Прокладка ищет переменную окружения или файл .rbenv_version, чтобы сообщить, какую версию Ruby нужно делегировать.

RVM:

RVM позволяет вам устанавливать версию Ruby напрямую, вызывая rvm use. Кроме того, он также отменяет системную команду cd. Когда вы cd в папку, содержащую файл .rvmrc, выполняется код внутри файла .rvmrc. Это можно использовать для установки версии Ruby или всего, что вам нравится.

Другие отличия:

Конечно, есть и другие отличия. RVM имеет gemsets из коробки, в то время как rbenv требует только немного большего взлома (но не много). Оба являются функциональными решениями проблемы.

5

Основное различие, по-видимому, когда и как рубин переключается. Рубин переключается:

  • для RVM вручную (использование rvm) или автоматически при изменении каталогов
  • для rbenv автоматически каждый раз, когда выполняется команда ruby ​​

RVM полагается на измененную команду cd и ручной выбор Ruby на rvm use. rbenv использует обертки или "прокладки" для всех основных команд ruby ​​в качестве механизма по умолчанию для выбора рубина. RVM создает обертки для базовых инструментов командной строки, таких как gem, rake, ruby. Они используются, например, в CronJobs (см. http://rvm.io/integration/cron/), но они не являются механизмом по умолчанию для переключения версии Ruby.

Таким образом, оба метода выбирают "автоматически" правильную версию Ruby путем перезаписи команд и использования оберток. rvm переопределяет команды оболочки, такие как cd. rbenv переопределяет все основные рубиновые команды, такие как ruby, irb, rake и gem.

5
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

to $PATH

Ещё вопросы

Сообщество Overcoder
Наверх
Меню