Comment RVM et Rbenv fonctionnent-ils réellement?

Je suis intéressé par la façon dont RVM et Rbenv fonctionnent réellement.

De toute évidence, ils échangent entre différentes versions de Ruby et de gemsets, mais comment cela se passe-t-il? J’avais supposé qu’ils mettaient simplement à jour les liens symboliques, mais après avoir fouillé le code (et je dois admettre que ma connaissance de Bash est superficielle), ils semblent faire plus que cela.

Brève explication: rbenv fonctionne en accrochant dans PATH votre environnement. Le concept est simple, mais le diable est dans les détails; plein scoop ci-dessous.

Tout d’abord, rbenv crée des shims pour toutes les commandes ( ruby , irb , rake , gem , etc.) sur toutes vos versions de Ruby installées. Ce processus est appelé rehashing . Chaque fois que vous installez une nouvelle version de Ruby ou installez un joyau qui fournit une commande, exécutez rbenv rehash pour vous assurer que les nouvelles commandes sont modifiées.

Ces cales vivent dans un seul répertoire ( ~/.rbenv/shims par défaut). Pour utiliser rbenv, il vous suffit d’append le répertoire shims au début de votre PATH :

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

Chaque fois que vous exécutez ruby partir de la ligne de commande, ou exécutez un script dont le nom lit #!/usr/bin/env ruby , votre système d’exploitation trouvera d’abord ~/.rbenv/shims/ruby et l’exécutera à la place de tout autre ruby exécutable que vous avez peut-être installé.

Chaque shim est un petit script Bash qui exécute à son tour rbenv exec . Donc, avec rbenv dans votre chemin, irb est équivalent à rbenv exec irb , et ruby -e "puts 42" est équivalent à rbenv exec ruby -e "puts 42" .

La commande rbenv exec détermine la version de Ruby que vous souhaitez utiliser, puis exécute la commande correspondante pour cette version. Voici comment:

  1. Si la variable d’environnement RBENV_VERSION est définie, sa valeur détermine la version de Ruby à utiliser.
  2. Si le répertoire de travail actuel possède un fichier .rbenv-version , son contenu est utilisé pour définir la variable d’environnement RBENV_VERSION .
  3. S’il n’y a pas de fichier .rbenv-version dans le répertoire en cours, rbenv recherche dans chaque répertoire parent un fichier .rbenv-version jusqu’à ce qu’il .rbenv-version la racine de votre système de fichiers. S’il en existe un, son contenu est utilisé pour définir la variable d’environnement RBENV_VERSION .
  4. Si RBENV_VERSION n’est toujours pas défini, rbenv essaie de le définir en utilisant le contenu du fichier ~/.rbenv/version .
  5. Si aucune version n’est spécifiée, rbenv suppose que vous voulez utiliser le Ruby “système”, c’est-à-dire quelle que soit la version qui sera exécutée si rbenv n’est pas sur votre chemin.

(Vous pouvez définir une version Ruby spécifique au projet avec la commande rbenv local , qui crée un fichier .rbenv-version dans le répertoire en cours. De même, la commande rbenv global modifie le fichier ~/.rbenv/version .)

Armé d’une variable d’environnement RBENV_VERSION , rbenv ajoute ~/.rbenv/versions/$RBENV_VERSION/bin au ~/.rbenv/versions/$RBENV_VERSION/bin de votre PATH , puis exécute la commande et les arguments passés à rbenv exec . Voila!

Pour un examen approfondi de ce qui se passe sous le capot, essayez de définir RBENV_DEBUG=1 et d’exécuter une commande Ruby. Chaque commande Bash exécutée par rbenv sera écrite sur votre terminal.


Maintenant, rbenv ne s’occupe que de changer de version, mais un écosystème prospère de plugins vous aidera à tout faire, de l’ installation de Ruby à la configuration de votre environnement , à la gestion des “gemsets” et à l’ automatisation des bundle exec .

Je ne suis pas sûr de savoir ce que le support IRC a à voir avec le changement de version de Ruby, et rbenv est conçu pour être suffisamment simple et compréhensible pour ne pas nécessiter de support. Mais si jamais vous avez besoin d’aide, le suivi des problèmes et Twitter ne sont qu’à quelques clics.

Divulgation: Je suis l’auteur de rbenv, ruby-build et rbenv-vars.

J’ai écrit un article en profondeur: http://niczsoft.com/2011/11/what-you-should-know-about-rbenv-and-rvm/

La différence de base réside dans la modification de l’environnement shell:

  • RVM: ça change quand on change Ruby.
  • rbenv: il est modifié lorsque vous exécutez un exécutable Ruby / gem.

De plus, le RVM couvre bien plus que la gestion de Rubies, mais bien plus que tout autre outil (il y en a d’autres que RVM et rbenv: https://twitter.com/#!/mpapis/ status / 171714447910502401 )

N’oubliez pas le support instantané que vous obtenez sur IRC dans le canal “#rvm” sur les serveurs Freenode.

Donc, pour résumer les excellentes réponses ci-dessus, la principale différence entre RVM et rbenv est lorsque la version de Ruby est sélectionnée.

rbenv:

rbenv ajoute une cale au début de votre chemin, une commande du même nom que Ruby. Lorsque vous tapez ruby sur une ligne de commande, le shim est exécuté à la place (car il est également appelé “ruby” et vient en premier dans le chemin). La cale recherche une variable d’environnement ou .rbenv_version fichier .rbenv_version pour lui indiquer la version de Ruby à déléguer.

RVM:

RVM vous permet de définir une version de Ruby directement en appelant l’ rvm use . De plus, il remplace également la commande cd system. Lorsque vous cd dans un dossier contenant un fichier .rvmrc , le code .rvmrc dans le fichier .rvmrc est exécuté. Cela peut être utilisé pour définir une version Ruby, ou toute autre chose que vous souhaitez.

Autres différences:

Il y a bien sûr d’autres différences. RVM a des gemsets hors de la boîte, alors que rbenv nécessite juste un peu plus de piratage (mais pas beaucoup). Les deux sont des solutions fonctionnelles au problème.

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

Vous donne à peu près:

 < 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 

Et il ajoute:

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

à $PATH

La principale différence semble être quand et comment Ruby est changé . Ruby est commuté:

  • pour RVM manuellement (utilisation rvm) ou automatiquement lors du changement de répertoire
  • pour rbenv automatiquement chaque fois qu’une commande ruby ​​est exécutée

RVM s’appuie sur la commande cd modifiée et la sélection manuelle de Ruby par rvm use . rbenv utilise les wrappers ou “shims” pour toutes les commandes ruby ​​de base comme mécanisme par défaut pour sélectionner ruby. RVM crée des wrappers pour les outils de ligne de commande de base tels que gem, rake, ruby. Ils sont utilisés par exemple dans CronJobs (voir http://rvm.io/integration/cron/ ), mais ils ne sont pas le mécanisme par défaut pour changer de version de Ruby.

Ainsi, les deux méthodes sélectionnent “automatiquement” la bonne version de Ruby en écrasant les commandes et en utilisant des wrappers. rvm remplace les commandes shell comme cd. rbenv remplace toutes les commandes ruby ​​de base telles que ruby, irb, rake et gem.