¿Cómo funcionan realmente RVM y rbenv?


Estoy interesado en cómo funcionan realmente RVM y rbenv.

Obviamente intercambian entre diferentes versiones de Ruby y gemsets, pero ¿cómo se logra esto? Había asumido que simplemente estaban actualizando enlaces simbólicos, pero después de haber profundizado en el código (y debo admitir que mi conocimiento de Bash es superficial) parecen estar haciendo más que esto.

Author: the Tin Man, 2012-02-22

5 answers

Breve explicación: rbenv funciona conectándose a PATH de su entorno. El concepto es simple, pero el diablo está en los detalles; primicia completa a continuación.

Primero, rbenv crea shims para todos los comandos (ruby, irb, rake, gem y así sucesivamente) en todas sus versiones instaladas de Ruby. Este proceso se llama rehashing. Cada vez que instale una nueva versión de Ruby o instale una gema que proporcione un comando, ejecute rbenv rehash para asegurarse de que los nuevos comandos son acuñada.

Estas cuñas viven en un solo directorio (~/.rbenv/shims por defecto). Para usar rbenv, solo necesita agregar el directorio shims al frente de su PATH:

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

Luego, cada vez que ejecute ruby desde la línea de comandos, o ejecute un script cuyo shebang diga #!/usr/bin/env ruby, su sistema operativo encontrará ~/.rbenv/shims/ruby primero y lo ejecutará en lugar de cualquier otro ejecutable ruby que pueda haber instalado.

Cada cuña es un pequeño script Bash que a su vez ejecuta rbenv exec. Así que con rbenv en su camino, irb es equivalente a rbenv exec irb, y ruby -e "puts 42" es equivalente a rbenv exec ruby -e "puts 42".

El comando rbenv exec calcula qué versión de Ruby desea usar, luego ejecuta el comando correspondiente para esa versión. He aquí cómo:

  1. Si se establece la variable de entorno RBENV_VERSION, su valor determina la versión de Ruby a usar.
  2. Si el directorio de trabajo actual tiene un archivo .rbenv-version, su contenido se utiliza para establecer la variable de entorno RBENV_VERSION.
  3. Si no hay un archivo .rbenv-version en el directorio actual, rbenv busca en cada directorio padre un archivo .rbenv-version hasta que llega a la raíz de su sistema de archivos. Si se encuentra uno, su contenido se utiliza para establecer la variable de entorno RBENV_VERSION.
  4. Si RBENV_VERSION todavía no está establecido, rbenv intenta establecerlo usando el contenido del archivo ~/.rbenv/version.
  5. Si no se especifica ninguna versión, rbenv asume que desea usar el Ruby "system", es decir, cualquier versión que se ejecutaría si rbenv no estuviera en su ruta.

(Puede establecer una versión de Ruby específica del proyecto con el comando rbenv local, que crea un archivo .rbenv-version en el directorio actual. Del mismo modo, el comando rbenv global modifica el archivo ~/.rbenv/version.)

Armado con una variable de entorno RBENV_VERSION, rbenv agrega ~/.rbenv/versions/$RBENV_VERSION/bin al frente de su PATH, luego ejecuta el comando y los argumentos pasados a rbenv exec. ¡Voila!

Para ver exactamente lo que sucede bajo el capó, intente configurar RBENV_DEBUG=1 y ejecutar un comando Ruby. Cada comando Bash que rbenv ejecuta será escrito a su terminal.


Ahora, rbenv solo se preocupa por cambiar versiones, pero un próspero ecosistema de complementos le ayudará a hacer todo, desde instalar Ruby hasta configurar su entorno, administrar "conjuntos de gemas" e incluso automatizar bundle exec.

No estoy muy seguro de qué tiene que ver el soporte de IRC con el cambio de versiones de Ruby, y rbenv está diseñado para ser lo suficientemente simple y comprensible como para no requerir soporte. Pero debería si alguna vez necesitas ayuda, el rastreador de problemas y Twitter están a solo un par de clics de distancia.

Revelación: Soy el autor de rbenv, ruby-build, y rbenv-vars.

 233
Author: Sam Stephenson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-23 23:27:33

Escribí un artículo en profundidad: http://niczsoft.com/2011/11/what-you-should-know-about-rbenv-and-rvm/

La diferencia básica es donde se cambia el entorno de shell:

  • RVM: cambia cuando cambias Ruby.
  • rbenv: cambia cuando se ejecuta un ejecutable Ruby/gem.

Además, lo que pasa con RVM es que cubre mucho más que solo administrar Rubíes, tiene mucho más que cualquier otra herramienta (hay otras aparte de RVM y rbenv: https://twitter.com/#! / mpapis / status/171714447910502401)

No se olvide del soporte instantáneo que obtiene en IRC en el canal "#rvm" en los servidores Freenode.

 18
Author: mpapis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-18 16:36:47

Así que para resumir las excelentes respuestas anteriores, la principal diferencia práctica entre RVM y rbenv es cuando se selecciona la versión de Ruby.

Rbenv:

Rbenv añade una cuña al inicio de tu ruta, un comando con el mismo nombre que Ruby. Cuando escribes ruby en una línea de comandos, el shim se ejecuta en su lugar (porque también se llama "ruby" y viene primero en la ruta). El shim busca una variable de entorno o un archivo .rbenv_version para indicarle qué versión de Ruby delegar a.

RVM:

RVM le permite establecer una versión de Ruby directamente llamando a rvm use. Además, también anula el comando del sistema cd. Cuando cd entra en una carpeta que contiene un archivo .rvmrc, se ejecuta el código dentro del archivo .rvmrc. Esto se puede usar para establecer una versión de Ruby, o cualquier otra cosa que te apetezca.

Otras diferencias:

Hay por supuesto otras diferencias. RVM tiene conjuntos de gemas listos para usar, mientras que rbenv requiere solo un poco más hacking (pero no mucho). Ambas son soluciones funcionales al problema.

 14
Author: superluminary,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-24 06:38:48
rvm system
env > before
rvm jruby # or whatever
env > after
diff after before

Te da aproximadamente:

< 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

Y precede:

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

A $PATH

 5
Author: Reactormonk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-18 16:37:14

La principal diferencia parece ser cuándo y cómo se cambia ruby. Ruby se cambia:

  • para RVM manualmente (uso de rvm) o automáticamente durante el cambio de directorios
  • para rbenv automáticamente cada vez que se ejecuta un comando ruby

RVM se basa en el comando modificado cd y la selección manual de Ruby por rvm use. rbenv usa wrappers o "shims" para todos los comandos básicos de ruby como el mecanismo por defecto para seleccionar ruby. RVM crea envoltorios para el comando básico herramientas de línea como gem, rake, ruby, también. Se utilizan por ejemplo en CronJobs (ver http://rvm.io/integration/cron / ), pero no son el mecanismo por defecto para cambiar la versión de Ruby.

Por lo tanto, ambos métodos seleccionan "automáticamente" la versión correcta de Ruby sobrescribiendo comandos y usando envoltorios. rvm anula comandos de shell como cd. rbenv anula todos los comandos básicos de ruby como ruby, irb, rake y gem.

 5
Author: 0x4a6f4672,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-20 14:53:56