Làm thế nào để RVM và rbenv thực sự hoạt động?


140

Tôi quan tâm đến cách RVM và rbenv thực sự hoạt động.

Rõ ràng là họ trao đổi giữa các phiên bản khác nhau của Ruby và đá quý, nhưng làm thế nào đạt được điều này? Tôi đã cho rằng họ chỉ đơn giản là đang cập nhật các liên kết tượng trưng, ​​nhưng đã đào sâu vào mã (và tôi phải thừa nhận kiến ​​thức của tôi về Bash là hời hợt) họ dường như đang làm nhiều hơn thế.

Câu trả lời:


241

Giải thích ngắn gọn: rbenv hoạt động bằng cách móc vào môi trường của bạn PATH. Khái niệm này là đơn giản, nhưng ma quỷ là trong các chi tiết; đầy đủ muỗng bên dưới.

Thứ nhất, rbenv tạo shims cho tất cả các lệnh ( ruby, irb, rake, gemvà vân vân) trên tất cả các phiên bản cài đặt của bạn của Ruby. Quá trình này được gọi là luyện lại . Mỗi khi bạn cài đặt phiên bản mới của Ruby hoặc cài đặt đá quý cung cấp lệnh, hãy chạy rbenv rehashđể đảm bảo mọi lệnh mới đều được hiển thị.

Những miếng chêm này sống trong một thư mục duy nhất ( ~/.rbenv/shimstheo mặc định). Để sử dụng rbenv, bạn chỉ cần thêm thư mục shims vào phía trước PATH:

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

Sau đó, bất cứ khi nào bạn chạy rubytừ dòng lệnh hoặc chạy tập lệnh mà shebang đọc #!/usr/bin/env ruby, hệ điều hành của bạn sẽ tìm thấy ~/.rbenv/shims/rubytrước và chạy nó thay vì bất kỳ tập lệnh rubythực thi nào khác mà bạn có thể đã cài đặt.

Mỗi shim là một đoạn script Bash nhỏ lần lượt chạy rbenv exec. Vì vậy, với rbenv trong đường dẫn của bạn, irbtương đương rbenv exec irbruby -e "puts 42"tương đương với rbenv exec ruby -e "puts 42".

Các rbenv execcon số lệnh ra những phiên bản của Ruby bạn muốn sử dụng, sau đó chạy các lệnh tương ứng cho phiên bản đó. Đây là cách thực hiện:

  1. Nếu RBENV_VERSIONbiến môi trường được đặt, giá trị của nó sẽ xác định phiên bản của Ruby sẽ sử dụng.
  2. Nếu thư mục làm việc hiện tại có một .rbenv-versiontệp, nội dung của nó được sử dụng để đặt RBENV_VERSIONbiến môi trường.
  3. Nếu không có .rbenv-versiontệp nào trong thư mục hiện tại, rbenv tìm kiếm từng thư mục cha cho một .rbenv-versiontệp cho đến khi nó chạm vào thư mục gốc của hệ thống tệp của bạn. Nếu một cái được tìm thấy, nội dung của nó được sử dụng để đặt RBENV_VERSIONbiến môi trường.
  4. Nếu RBENV_VERSIONvẫn không được đặt, rbenv cố gắng đặt nó bằng cách sử dụng nội dung của ~/.rbenv/versiontệp.
  5. Nếu không có phiên bản nào được chỉ định ở bất cứ đâu, rbenv giả định rằng bạn muốn sử dụng "hệ thống" Ruby Biệt, tức là bất kỳ phiên bản nào sẽ được chạy nếu rbenv không có trong đường dẫn của bạn.

(Bạn có thể đặt phiên bản Ruby dành riêng cho dự án bằng rbenv locallệnh tạo .rbenv-versiontệp trong thư mục hiện tại. Tương tự, rbenv globallệnh sẽ sửa đổi ~/.rbenv/versiontệp.)

Được trang bị một RBENV_VERSIONbiến môi trường, rbenv thêm ~/.rbenv/versions/$RBENV_VERSION/binvào phía trước của bạn PATH, sau đó thực thi lệnh và các đối số được truyền cho rbenv exec. Voila!

Để có cái nhìn thấu đáo về chính xác những gì xảy ra dưới mui xe, hãy thử cài đặt RBENV_DEBUG=1và chạy lệnh Ruby. Mỗi lệnh Bash mà rbenv chạy sẽ được ghi vào thiết bị đầu cuối của bạn.


Bây giờ, rbenv chỉ quan tâm đến việc chuyển đổi các phiên bản, nhưng một hệ sinh thái thịnh vượng của các plugin sẽ giúp bạn làm mọi thứ, từ cài đặt Ruby đến thiết lập môi trường của bạn , quản lý "đá quý" và thậm chí tự động hóabundle exec .

Tôi không chắc chắn những gì hỗ trợ IRC phải làm khi chuyển đổi các phiên bản Ruby và rbenv được thiết kế đơn giản và đủ dễ hiểu để không yêu cầu hỗ trợ. Nhưng nếu bạn cần trợ giúp, trình theo dõi vấn đề và Twitter chỉ là một vài cú nhấp chuột.

Tiết lộ: Tôi là tác giả của rbenv, ruby-build và rbenv-vars.


14
Cảm ơn bạn đã dành thời gian để đưa ra một câu trả lời tuyệt vời như vậy.
siêu sáng

2
Wow, cảm ơn vì một lời giải thích dễ hiểu và dễ hiểu. Một giáo viên bẩm sinh.
racl101

Này, Sam, vì câu trả lời này đã được hai tuổi, bạn có muốn cập nhật gì không? Chắc chắn một cái gì đó đã được thay đổi trong rbenv kể từ thời điểm đó.
Nakilon

Không. Mô tả về hacker hay nhất tôi từng thấy. Tôi nghĩ rằng bản cập nhật duy nhất cần thay đổi trong đó là liên kết đến rbenv-gemet (liên kết vẫn sẽ đưa bạn đến đó. Đây chỉ là một bước nữa từ chuyển hướng).
Jeffrey 'jf' Lim

18

Tôi đã viết một bài viết chuyên sâu: http://niczsoft.com/2011/11/what-you-should-ledge-about-rbenv-and-rvm/

Sự khác biệt cơ bản là nơi môi trường vỏ được thay đổi:

  • RVM: nó đã thay đổi khi bạn thay đổi Ruby.
  • rbenv: nó đã thay đổi khi bạn chạy một tệp thực thi Ruby / gem.

Ngoài ra, vấn đề của RVM là, nó bao gồm rất nhiều thứ sau đó chỉ là quản lý Rubies, nó có nhiều hơn bất kỳ công cụ nào khác (có những công cụ khác ngoài RVM và rbenv: https://twitter.com/#!/mpapis/ trạng thái / 171714447910502401 )

Đừng quên hỗ trợ tức thì mà bạn nhận được trên IRC trong kênh "#rvm" trên các máy chủ Freenode.


1
Cảm ơn, thật tuyệt khi mọi người từ cả hai cộng đồng đều tham gia.
siêu sáng

15

Vì vậy, để tóm tắt các câu trả lời xuất sắc ở trên, sự khác biệt thực tế chính giữa RVM và rbenv là khi phiên bản của Ruby được chọn.

rbenv:

rbenv thêm một shim vào đầu con đường của bạn, một lệnh có cùng tên với Ruby. Khi bạn gõ rubyvào một dòng lệnh, shim sẽ được chạy thay thế (bởi vì nó còn được gọi là "ruby" và đứng đầu trong đường dẫn). Shim tìm kiếm một biến môi trường hoặc .rbenv_versiontệp để cho nó biết phiên bản nào của Ruby được ủy quyền.

RVM:

RVM cho phép bạn đặt phiên bản Ruby trực tiếp bằng cách gọi rvm use. Ngoài ra, nó cũng ghi đè cdlệnh hệ thống. Khi bạn cdvào một thư mục chứa .rvmrctệp, mã bên trong .rvmrctệp sẽ được thực thi. Điều này có thể được sử dụng để đặt phiên bản Ruby hoặc bất cứ thứ gì bạn thích.

Sự khác biệt khác:

Tất nhiên có sự khác biệt khác. RVM có đá quý trong hộp, trong khi rbenv chỉ cần hack thêm một chút (nhưng không nhiều). Cả hai đều là giải pháp chức năng cho vấn đề.


6

Sự khác biệt chính dường như là khi và cách ruby ​​được chuyển đổi . Ruby được chuyển đổi:

  • cho RVM thủ công (sử dụng rvm) hoặc tự động trong khi thay đổi thư mục
  • cho rbenv tự động mỗi khi lệnh ruby ​​được thực thi

RVM dựa vào cdlệnh được sửa đổi và lựa chọn thủ công của Ruby bằng cách rvm use. rbenv sử dụng các hàm bao hoặc "shims" cho tất cả các lệnh ruby ​​cơ bản làm cơ chế mặc định để chọn ruby. RVM tạo các hàm bao cho các công cụ dòng lệnh cơ bản như gem, rake, ruby, quá. Chúng được sử dụng ví dụ trong CronJobs (xem http://rvm.io/integration/cron/ ), nhưng chúng không phải là cơ chế mặc định để chuyển đổi phiên bản Ruby.

Do đó, cả hai phương pháp đều chọn "tự động" phiên bản Ruby đúng bằng cách ghi đè các lệnh và sử dụng các hàm bao. rvm ghi đè các lệnh shell như cd. rbenv ghi đè tất cả các lệnh ruby ​​cơ bản như ruby, irb, rake và gem.


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

Cung cấp cho bạn khoảng:

< 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

Và nó chuẩn bị:

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

đến $PATH

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.