RVM และ rbenv ทำงานอย่างไร


140

ฉันสนใจว่า RVM และ rbenv ทำงานอย่างไร

เห็นได้ชัดว่าพวกเขาสลับระหว่างรุ่นต่าง ๆ ของ Ruby และ gemsets แต่สิ่งนี้สำเร็จ ฉันสันนิษฐานว่าพวกเขาเพียงแค่อัปเดต symlink แต่การเจาะลึกเข้าไปในโค้ด (และฉันต้องยอมรับความรู้ของฉันเกี่ยวกับ Bash นั้นเป็นเพียงผิวเผิน) พวกเขาดูเหมือนจะทำอะไรมากกว่านี้

คำตอบ:


241

คำอธิบายสั้น ๆ : rbenv ทำงานโดยเชื่อมต่อกับสภาพแวดล้อมของPATHคุณ แนวคิดนั้นง่าย แต่ปีศาจอยู่ในรายละเอียด ตักเต็มรูปแบบด้านล่าง

ครั้งแรก rbenv สร้างshimsสำหรับคำสั่งทั้งหมด ( ruby, irb, rake, gemและอื่น ๆ ) ข้ามรุ่นที่ติดตั้งทั้งหมดของคุณจากทับทิม กระบวนการนี้เรียกว่าrehashing ทุกครั้งที่คุณติดตั้ง Ruby เวอร์ชันใหม่หรือติดตั้ง gem ที่จัดเตรียมคำสั่งให้รันrbenv rehashเพื่อให้แน่ใจว่าคำสั่งใหม่ใด ๆ ถูกกำหนดไว้

shims เหล่านี้มีชีวิตอยู่ในไดเรกทอรีเดียว ( ~/.rbenv/shimsโดยค่าเริ่มต้น) ในการใช้ rbenv คุณต้องเพิ่มไดเรกทอรี shims ไว้ด้านหน้าPATH:

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

จากนั้นเมื่อใดก็ตามที่คุณเรียกใช้rubyจากบรรทัดคำสั่งหรือเรียกใช้สคริปต์ที่มี shebang อ่าน#!/usr/bin/env rubyอยู่ระบบปฏิบัติการของคุณจะค้นหา~/.rbenv/shims/rubyก่อนและเรียกใช้งานแทนที่จะเป็นอื่น ๆrubyปฏิบัติการคุณอาจติดตั้ง

ชิมแต่ละตัวเป็นสคริปต์ Bash ขนาดเล็กที่ทำงานในทางกลับrbenv execกัน ดังนั้นด้วย rbenv ในเส้นทางของคุณirbเท่ากับrbenv exec irbและruby -e "puts 42"เทียบเท่าrbenv exec ruby -e "puts 42"เทียบเท่ากับ

rbenv execตัวเลขคำสั่งออกจากสิ่งที่รุ่นของทับทิมคุณต้องการใช้งานแล้วรันคำสั่งที่เกี่ยวข้องสำหรับรุ่นที่ นี่คือวิธี:

  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แล้วผู้บริหารคำสั่งและการขัดแย้งผ่านไปVoila!

หากต้องการดูสิ่งที่เกิดขึ้นภายใต้ประทุนอย่างละเอียดลองตั้งค่าRBENV_DEBUG=1และเรียกใช้คำสั่ง Ruby ทุกคำสั่ง Bash ที่ rbenv ทำงานจะถูกเขียนไปยังเทอร์มินัลของคุณ


ตอนนี้ rbenv เป็นห่วงเพียงกับรุ่นเปลี่ยน แต่ระบบนิเวศที่เจริญรุ่งเรืองของปลั๊กอินจะช่วยให้คุณทำทุกอย่างจากการติดตั้งทับทิมที่จะตั้งค่าสภาพแวดล้อมของคุณ , การจัดการ "gemsets"และแม้กระทั่งการทำงานอัตโนมัติbundle execการทำงานอัตโนมัติ

ฉันไม่แน่ใจว่าสิ่งที่สนับสนุน IRC เกี่ยวข้องกับการสลับรุ่น Ruby และ rbenv ได้รับการออกแบบให้เรียบง่ายและเข้าใจง่ายพอที่จะไม่ต้องการการสนับสนุน แต่หากคุณต้องการความช่วยเหลือตัวติดตามปัญหาและ Twitter เป็นเพียงไม่กี่คลิก

การเปิดเผยข้อมูล: ฉันเป็นผู้แต่ง rbenv, ruby-build และ rbenv-vars


14
ขอบคุณที่สละเวลาตอบอย่างยอดเยี่ยม
superluminary

2
ว้าวขอบคุณมากสำหรับคำอธิบายที่เข้าใจได้และเข้าใจได้ ครูที่เกิดมาโดยธรรมชาติ
racl101

เฮ้แซมเนื่องจากคำตอบนี้มีอายุสองปีคุณต้องการอัปเดตหรือไม่ แน่นอนบางสิ่งบางอย่างมีการเปลี่ยนแปลงใน rbenv ตั้งแต่เวลานั้น
Nakilon

Nope คำอธิบายแฮ็กเกอร์ที่ดีที่สุดที่ฉันเคยเห็น ฉันคิดว่าการอัปเดตเดียวที่จำเป็นต้องเปลี่ยนคือไปที่ลิงก์ไปยัง rbenv-gemset (ลิงก์จะยังนำคุณไปถึงที่นั่นมันเป็นอีกขั้นตอนพิเศษจากการเปลี่ยนเส้นทาง)
เจฟฟรีย์ 'jf' Lim

18

ฉันเขียนบทความเชิงลึก: http://niczsoft.com/2011/11/what-you-should-know-about-rbenv-and-rvm/

ความแตกต่างพื้นฐานคือที่ซึ่งสภาพแวดล้อมของเชลล์เปลี่ยนไป:

  • RVM: มันเปลี่ยนไปเมื่อคุณเปลี่ยน Ruby
  • rbenv: มันเปลี่ยนไปเมื่อคุณรันโปรแกรม Ruby / gem

นอกจากนี้สิ่งที่เกี่ยวกับ RVM คือมันครอบคลุมมากขึ้นแล้วเพียงแค่จัดการ Rubies แต่ก็มีมากกว่าเครื่องมืออื่น ๆ (มีคนอื่นนอกเหนือจาก RVM และ rbenv: https://twitter.com/#!/mpapis/ สถานะ / 171714447910502401 )

อย่าลืมการสนับสนุนทันทีที่คุณได้รับจาก IRC ในช่อง "#rvm" บนเซิร์ฟเวอร์ Freenode


1
ขอบคุณมันยอดเยี่ยมมากที่ผู้คนจากชุมชนทั้งสองเข้าร่วม
superluminary

15

ดังนั้นเพื่อสรุปคำตอบที่ดีเลิศข้างต้นความแตกต่างในทางปฏิบัติที่สำคัญระหว่าง RVM และ rbenv คือเมื่อเลือกรุ่นของ Ruby

rbenv:

rbenv เพิ่ม shim ให้กับจุดเริ่มต้นของพา ธ ของคุณคำสั่งที่มีชื่อเหมือนกับ Ruby เมื่อคุณพิมพ์rubyที่บรรทัดคำสั่ง shim จะถูกเรียกใช้แทน (เนื่องจากเรียกอีกอย่างว่า "ruby" และมาก่อนในพา ธ ) shim ค้นหาตัวแปรสภาพแวดล้อมหรือ.rbenv_versionไฟล์เพื่อบอกเวอร์ชันของ Ruby ที่จะมอบสิทธิ์ให้

RVM:

RVM rvm useช่วยให้คุณกำหนดรุ่นของทับทิมโดยตรงโดยการเรียก นอกจากนี้มันยังแทนที่cdคำสั่งระบบ เมื่อคุณcdเข้าไปในโฟลเดอร์ที่มี.rvmrcไฟล์รหัสอยู่ภายใน.rvmrcไฟล์จะถูกเรียกใช้งาน สามารถใช้เพื่อตั้งค่าเวอร์ชัน Ruby หรืออะไรก็ได้ที่คุณนึกออก

ความแตกต่างอื่น ๆ :

มีความแตกต่างอื่น ๆ แน่นอน RVM มีอัญมณีออกมาจากกล่องในขณะที่ rbenv ต้องการการแฮ็คเพียงเล็กน้อย (แต่ไม่มาก) ทั้งสองเป็นวิธีแก้ไขปัญหาการทำงาน


6

ความแตกต่างที่สำคัญน่าจะเป็น เมื่อใดและอย่างไรทับทิมจะเปลี่ยน Ruby ถูกสวิตช์:

  • สำหรับ RVM ด้วยตนเอง (ใช้ rvm) หรือโดยอัตโนมัติในระหว่างการเปลี่ยนไดเรกทอรี
  • สำหรับ rbenv โดยอัตโนมัติทุกครั้งที่คำสั่ง ruby ​​ถูกเรียกใช้งาน

RVM ขึ้นอยู่กับcdคำสั่งที่แก้ไขและการเลือก Ruby ด้วยrvm useตนเอง rbenv ใช้ wrappers หรือ "shims" สำหรับคำสั่ง ruby ​​พื้นฐานทั้งหมดเป็นกลไกเริ่มต้นเพื่อเลือก ruby RVM สร้าง wrappers สำหรับเครื่องมือบรรทัดคำสั่งพื้นฐานเช่น gem, rake, ruby ​​ด้วย ตัวอย่างเหล่านี้ถูกใช้ใน CronJobs (ดูhttp://rvm.io/integration/cron/ ) แต่ไม่ใช่กลไกเริ่มต้นในการสลับรุ่น Ruby

ดังนั้นทั้งสองวิธีจึงเลือก "Ruby" รุ่นทับทิมที่ถูกต้องโดยการเขียนทับคำสั่งและใช้ wrappers 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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.