2012-02-22 18 views
131

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

Obviamente, cambian entre las diferentes versiones de Ruby y de las gemas, pero ¿cómo se consigue? Supuse que simplemente estaban actualizando enlaces simbólicos, pero habiendo profundizado en el código (y debo admitir que mi conocimiento de Bash es superficial) parecen estar haciendo más que esto.

Respuesta

225

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

En primer lugar, crea rbenv cuñas para todos los comandos (ruby, irb, rake, gem y así sucesivamente) en todas sus versiones instaladas de Ruby. Este proceso se llama reformulando. 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 todos los nuevos comandos estén ajustados.

Estas calzas viven en un solo directorio (~/.rbenv/shims por defecto). Para utilizar rbenv, sólo tiene que añadir el directorio de cuñas para el frente de su PATH:

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

Entonces, cualquier vez que se ejecuta ruby desde la línea de comandos, o ejecutar una secuencia de comandos cuya tinglado lee #!/usr/bin/env ruby, el sistema operativo se encuentra ~/.rbenv/shims/ruby primero y ejecútelo en lugar de cualquier otro ejecutable ruby que pueda haber instalado.

Cada shim es un pequeño script Bash que a su vez ejecuta rbenv exec. Entonces 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 determina qué versión de Ruby desea usar, luego ejecuta el comando correspondiente para esa versión. Aquí se explica cómo:

  1. Si se establece la variable de entorno RBENV_VERSION, su valor determina la versión de Ruby que se utilizará.
  2. Si el directorio de trabajo actual tiene un archivo .rbenv-version, su contenido se usa 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 principal un archivo .rbenv-version hasta que llegue a la raíz de su sistema de archivos. Si se encuentra uno, su contenido se usa para establecer la variable de entorno RBENV_VERSION.
  4. Si RBENV_VERSION aún no está configurado, rbenv intenta configurarlo utilizando el contenido del archivo ~/.rbenv/version.
  5. Si no se especifica ninguna versión en cualquier lugar, rbenv asume que desea utilizar el "sistema" Ruby-i.e. cualquiera que sea la versión se ejecutará si rbenv no estuviera en su camino.

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

Armado con un RBENV_VERSION variable de entorno, 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 una visión detallada de lo que ocurre exactamente debajo del capó, intente configurar RBENV_DEBUG=1 y ejecute un comando de Ruby. Cada comando de Bash que ejecute rbenv se escribirá en su terminal.


Ahora, rbenv sólo se preocupa con las versiones de conmutación, sino un próspero ecosistema de plugins le ayudará a hacer todo lo installing Ruby-setting up your environment, managing "gemsets" e incluso automating bundle exec.

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

Divulgación: soy el autor de rbenv, ruby-build, y rbenv-vars.

+13

Gracias por tomarse el tiempo para dar una respuesta tan excelente. – superluminary

+2

Guau, gracias por una explicación comprensible y comprensible. Un maestro nacido natural. – racl101

+2

parece que .ruby-version también lo haría. – alexzg

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

que 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/[email protected] 
*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 antepone:

$HOME/.rvm/gems/jruby-1.6.6/bin:$HOME/.rvm/gems/[email protected]/bin 

a $PATH

18

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

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

  • RVM: se cambia cuando se cambia Ruby.
  • rbenv: ha cambiado al ejecutar un ejecutable Ruby/gem.

también, lo que pasa con RVM es, que cubre mucho más que sólo la gestión de los rubíes, que tiene mucho más que cualquier otra herramienta (hay otros aparte de RVM y rbenv: https://twitter.com/#!/mpapis/status/171714447910502401)

Do No olvide la asistencia instantánea que obtiene en IRC en el canal "#rvm" en los servidores de Freenode.

+1

Gracias, es realmente genial que personas de ambas comunidades se estén involucrando. – superluminary

13

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 para el inicio de su trayectoria, un comando con el mismo nombre que Ruby. Cuando escribe ruby en una línea de comando, la corrección se ejecuta en su lugar (porque también se llama "ruby" y ocupa el primer lugar en la ruta). El shim busca una variable de entorno o un archivo .rbenv_version para indicarle a qué versión de Ruby delegar.

RVM:

RVM le permite establecer una versión de Rubí directamente llamando rvm use. Además, también anula el comando del sistema cd. Cuando se cd 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:

Por supuesto, hay otras diferencias. RVM tiene gemsets fuera de la caja, mientras que rbenv requiere un poco más de pirateo (pero no mucho). Ambas son soluciones funcionales para el problema.

5

La diferencia principal parece ser when and how ruby is switched. Rubí se enciende:

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

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

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

Cuestiones relacionadas