Bagaimana cara RVM dan rbenv bekerja?

140

Saya tertarik pada bagaimana sebenarnya RVM dan rbenv bekerja.

Jelas mereka bertukar antara versi Ruby dan permata yang berbeda, tetapi bagaimana hal ini dicapai? Saya berasumsi mereka hanya memperbarui symlink, tetapi setelah mempelajari kode (dan saya harus mengakui pengetahuan saya tentang Bash dangkal) mereka tampaknya melakukan lebih dari ini.

superluminary
sumber

Jawaban:

241

Penjelasan singkat: rbenv bekerja dengan menghubungkan ke lingkungan Anda PATH. Konsepnya sederhana, tetapi iblis ada dalam rinciannya; sendok penuh di bawah ini.

Pertama, rbenv menciptakan shims untuk semua perintah ( ruby, irb, rake, gemdan sebagainya) di semua versi Anda terpasang Ruby. Proses ini disebut pengulangan . Setiap kali Anda menginstal Ruby versi baru atau memasang permata yang menyediakan perintah, jalankan rbenv rehashuntuk memastikan setiap perintah baru tidak diikutsertakan.

Shims ini hidup dalam satu direktori ( ~/.rbenv/shimssecara default). Untuk menggunakan rbenv, Anda hanya perlu menambahkan direktori shims di bagian depan PATH:

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

Kemudian setiap kali Anda menjalankan rubydari baris perintah, atau menjalankan skrip yang dibaca oleh shebang #!/usr/bin/env ruby, sistem operasi Anda akan menemukannya ~/.rbenv/shims/rubyterlebih dahulu dan menjalankannya alih-alih rubyexecutable lain yang mungkin telah Anda instal.

Setiap shim adalah skrip Bash kecil yang pada gilirannya berjalan rbenv exec. Jadi dengan rbenv di jalur Anda, irbsama dengan rbenv exec irb, dan ruby -e "puts 42"setara dengan rbenv exec ruby -e "puts 42".

The rbenv exectokoh perintah apa versi Ruby yang ingin Anda gunakan, kemudian menjalankan perintah yang sesuai untuk versi itu. Begini caranya:

  1. Jika RBENV_VERSIONvariabel lingkungan diatur, nilainya menentukan versi Ruby untuk digunakan.
  2. Jika direktori kerja saat ini memiliki .rbenv-versionfile, isinya digunakan untuk mengatur RBENV_VERSIONvariabel lingkungan.
  3. Jika tidak ada .rbenv-versionfile di direktori saat ini, rbenv mencari setiap direktori induk untuk suatu .rbenv-versionfile sampai menyentuh root sistem file Anda. Jika ditemukan, isinya digunakan untuk mengatur RBENV_VERSIONvariabel lingkungan.
  4. Jika RBENV_VERSIONmasih belum disetel, rbenv mencoba mengaturnya menggunakan konten ~/.rbenv/versionfile.
  5. Jika tidak ada versi yang ditentukan di mana saja, rbenv mengasumsikan Anda ingin menggunakan Ruby "sistem" —yaitu versi apa pun yang akan dijalankan jika rbenv tidak ada di jalur Anda.

(Anda dapat mengatur versi Ruby khusus proyek dengan rbenv localperintah, yang membuat .rbenv-versionfile di direktori saat ini. Demikian pula, rbenv globalperintah memodifikasi ~/.rbenv/versionfile.)

Dipersenjatai dengan RBENV_VERSIONvariabel lingkungan, rbenv menambah ~/.rbenv/versions/$RBENV_VERSION/binbagian depan Anda PATH, kemudian mengeksekusi perintah dan argumen yang diteruskan rbenv exec. Voila!

Untuk melihat secara seksama apa yang terjadi di bawah tenda, coba setel RBENV_DEBUG=1dan jalankan perintah Ruby. Setiap perintah Bash yang dijalankan rbenv akan ditulis ke terminal Anda.


Sekarang, rbenv hanya peduli dengan beralih versi, tetapi ekosistem plugin yang berkembang akan membantu Anda melakukan segalanya mulai dari menginstal Ruby hingga mengatur lingkungan Anda , mengelola "permata" dan bahkan mengotomatisasibundle exec .

Saya tidak yakin apa yang harus dilakukan dukungan IRC dengan beralih versi Ruby, dan rbenv dirancang untuk menjadi sederhana dan cukup dimengerti untuk tidak memerlukan dukungan. Tetapi jika Anda membutuhkan bantuan, pelacak masalah dan Twitter hanya dengan beberapa klik saja.

Pengungkapan: Saya adalah penulis rbenv, ruby-build, dan rbenv-vars.

Sam Stephenson
sumber
14
Terima kasih telah meluangkan waktu untuk memberikan jawaban yang luar biasa.
superluminary
2
Wow, terima kasih atas penjelasan yang bisa dipahami dan dimengerti. Guru yang lahir alami.
racl101
Hai, Sam, karena jawaban ini berumur dua tahun, apakah Anda ingin membuat pembaruan? Tentunya ada sesuatu yang berubah di rbenv sejak saat itu.
Nakilon
Nggak. Deskripsi peretas terbaik yang pernah saya lihat. Saya pikir satu-satunya pembaruan yang perlu diubah di sana adalah tautan ke rbenv-gemset (tautan itu masih akan membawa Anda ke sana. Ini hanyalah langkah tambahan dari pengalihan).
Jeffrey 'jf' Lim
18

Saya menulis artikel mendalam: http://niczsoft.com/2011/11/what-you-should-know-about-rbenv-and-rvm/

Perbedaan mendasar adalah di mana lingkungan shell diubah:

  • RVM: itu berubah ketika Anda mengubah Ruby.
  • rbenv: itu berubah ketika Anda menjalankan Ruby / gem executable.

Juga, hal tentang RVM adalah, ia mencakup lebih dari sekadar mengelola Rubi, ia memiliki lebih banyak daripada alat lainnya (ada yang lain selain RVM dan rbenv: https://twitter.com/#!/mpapis/ status / 171714447910502401 )

Jangan lupa tentang dukungan instan yang Anda dapatkan di IRC di saluran "#rvm" di server Freenode.

mpapis
sumber
1
Terima kasih, sungguh luar biasa bahwa orang-orang dari kedua komunitas terlibat.
superluminary
15

Jadi untuk meringkas jawaban yang sangat baik di atas, perbedaan praktis utama antara RVM dan rbenv adalah ketika versi Ruby dipilih.

rbenv:

rbenv menambahkan shim ke awal jalur Anda, perintah dengan nama yang sama dengan Ruby. Ketika Anda mengetik rubypada baris perintah, shim dijalankan sebagai gantinya (karena itu juga disebut "ruby" dan datang pertama kali di jalan). Shim mencari variabel lingkungan atau .rbenv_versionfile untuk menentukan versi Ruby mana yang akan didelegasikan.

RVM:

RVM memungkinkan Anda untuk mengatur versi Ruby secara langsung dengan menelepon rvm use. Selain itu, ini juga mengesampingkan cdperintah sistem. Saat Anda cdmasuk ke folder yang berisi .rvmrcfile, kode di dalam .rvmrcfile dieksekusi. Ini dapat digunakan untuk mengatur versi Ruby, atau apa pun yang Anda suka.

Perbedaan lainnya:

Tentu saja ada perbedaan lain. RVM memiliki permata di luar kotak, sementara rbenv hanya membutuhkan sedikit peretasan (tapi tidak banyak). Keduanya merupakan solusi fungsional untuk masalah tersebut.

superluminary
sumber
6

Perbedaan utamanya adalah kapan dan bagaimana ruby ​​diaktifkan . Ruby diaktifkan:

  • untuk RVM secara manual (penggunaan rvm) atau secara otomatis selama pergantian direktori
  • untuk rbenv secara otomatis setiap kali perintah ruby ​​dijalankan

RVM mengandalkan cdperintah yang dimodifikasi dan pemilihan manual Ruby oleh rvm use. rbenv menggunakan pembungkus atau "shims" untuk semua perintah ruby ​​dasar sebagai mekanisme default untuk memilih ruby. RVM membuat pembungkus untuk alat-alat baris perintah dasar seperti permata, menyapu, ruby, juga. Mereka digunakan misalnya di CronJobs (lihat http://rvm.io/integration/cron/ ), tetapi itu bukan mekanisme default untuk mengganti versi Ruby.

Jadi kedua metode pilih "secara otomatis" versi Ruby yang tepat dengan menimpa perintah dan menggunakan pembungkus. rvm mengesampingkan perintah shell seperti cd. rbenv mengesampingkan semua perintah ruby ​​dasar seperti ruby, irb, rake dan gem.

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

Memberi Anda sekitar:

< 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

Dan itu menambahkan:

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

untuk $PATH

Reactormonk
sumber