Як реально працюють RVM та rbenv?


140

Мене цікавить, як реально працюють RVM та rbenv.

Очевидно, вони обмінюються різними версіями Ruby та gemsets, але як цього досягти? Я припускав, що вони просто оновлюють символьні посилання, але заглибившись у код (і я повинен визнати, що мої знання про Баша є поверхневими), здається, вони роблять більше, ніж це.

Відповіді:


241

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

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

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

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

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

Кожна лайка - це крихітний сценарій Баша, який у свою чергу працює rbenv exec. Отже, з rbenv на вашому шляху irbеквівалентний rbenv exec irbі ruby -e "puts 42"еквівалентний rbenv exec ruby -e "puts 42".

Ці rbenv execцифри команди, яка версія Ruby , яку ви хочете використовувати, а потім запускає відповідну команду для цієї версії. Ось як:

  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 не був на вашому шляху.

(Ви можете встановити проектну версію 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
Нічого, дякую за таке зрозуміле і зрозуміле пояснення. Народжений учитель.
racl101

Гей, Сем, оскільки цій відповіді два роки, ти хотів би зробити якісь оновлення? Звичайно, в rbenv щось змінилося з того часу.
Накілон

Ні. Найкращий опис хакера, який я коли-небудь бачив. Я думаю, що єдине оновлення, яке потрібно змінити там, - це посилання на rbenv-gemset (посилання все одно потрапить до вас. Це лише ще один додатковий крок від переадресації).
Джеффрі 'jf' Лім

18

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

Основна відмінність полягає в тому, де змінюється середовище оболонки:

  • RVM: це змінюється, коли ви змінюєте Ruby.
  • rbenv: це змінюється під час запуску виконуваного файлу Ruby / gem.

Крім того, річ у RVM полягає в тому, що вона охоплює набагато більше, ніж просто керування рубінами, у неї набагато більше, ніж у будь-якого іншого інструмента (крім RVM та rbenv є й інші: https://twitter.com/#!/mpapis/ статус / 171714447910502401 )

Не забувайте про миттєву підтримку, яку ви отримуєте на IRC в каналі "#rvm" на серверах Freenode.


1
Дякую, це дійсно чудово, що люди з обох громад залучаються.
надсвітковий

15

Отже, підсумовуючи відмінні відповіді вище, головна практична відмінність RVM від rbenv полягає у виборі версії Ruby.

rbenv:

rbenv додає пробіл на початок вашого шляху, команду з тим же ім'ям, як Ruby. Коли ви вводите rubyкомандний рядок, замість цього запускається shim (тому що він також називається "ruby" і стає першим на шляху). Шим шукає змінну середовища або .rbenv_versionфайл, щоб повідомити, до якої версії Ruby делегувати.

RVM:

RVM дозволяє встановити версію Ruby безпосередньо, зателефонувавши rvm use. Крім того, він також перекриває cdсистемну команду. Коли ви знаходитесь cdу папці, яка містить .rvmrcфайл, .rvmrcвиконується код всередині файлу. Це можна використовувати для встановлення версії Ruby або будь-якого іншого, що вам здається.

Інші відмінності:

Звичайно, є й інші відмінності. RVM має гемсети поза коробкою, тоді як rbenv вимагає трохи більше хакерства (але не дуже багато). Обидва є функціональними рішеннями проблеми.


6

Основна різниця, здається, полягає в тому, коли і як перемикається рубін . Рубі перемикається:

  • для RVM вручну (використання rvm) або автоматично під час зміни каталогів
  • для rbenv автоматично кожного разу, коли виконується команда ruby

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

Таким чином, обидва способи вибирають "автоматично" правильну версію Ruby, перезаписуючи команди та використовуючи обгортки. rvm переосмислює команди оболонки, такі як CD. rbenv замінює всі основні команди ruby, такі як 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

до $PATH

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.