TL;DR
macOS đi kèm với một bản Ruby hệ thống mà bạn không thể ghi vào — Apple đã khóa nó có chủ ý. Cách tốt nhất là cài Ruby thông qua rbenv hoặc Homebrew để bạn làm việc với bản sao của riêng mình, không phải của Apple. Cần giải quyết trong vòng hai phút? Chuyển thẳng xuống phần workaround --user-install bên dưới.
Lỗi chính xác
ERROR: While executing gem ... (Gem::FilePermissionError)
You don't have write permissions for the /Library/Ruby/Gems/2.6.0 directory.
Lỗi này xuất hiện khi shell của bạn đang trỏ vào /usr/bin/ruby — bản Ruby đi kèm với macOS. Thư mục đó thuộc sở hữu của root và được bảo vệ bởi System Integrity Protection (SIP). Đáng chú ý là sudo gem install cũng không giải quyết được vấn đề. Trên các phiên bản macOS mới hơn, lệnh này hoặc thất bại hoàn toàn, hoặc thành công một nửa theo cách gây ra rắc rối về sau.
Tại sao lỗi này xảy ra
Apple tích hợp Ruby như một tiện ích cho các công cụ tích hợp sẵn của mình, chứ không phải như một runtime để bạn tự quản lý. Kể từ macOS Catalina, phân vùng hệ thống ở hầu hết các khu vực là chỉ đọc. SIP chặn việc ghi vào các thư mục thuộc sở hữu hệ thống ngay cả khi có quyền root.
Tệp nhị phân /usr/bin/ruby bị khóa cứng ở phiên bản 2.6.x — rất cũ theo chuẩn Ruby, trong khi phiên bản ổn định hiện tại là 3.3.x. Nó chưa bao giờ được thiết kế để làm Ruby cho mục đích phát triển của bạn. Chạy lệnh sau trong một terminal mới để xác nhận tình trạng hiện tại:
$ which ruby
/usr/bin/ruby
$ ruby -v
ruby 2.6.10p210 (2022-04-12 revision 67958) [universal.arm64e-darwin23]
Nếu thấy /usr/bin/ruby ở đó, mọi lệnh gem install bạn chạy đều sẽ gặp lỗi này.
Cách sửa 1: Cài rbenv (Khuyến nghị)
rbenv quản lý nhiều phiên bản Ruby song song mà không đụng vào các tệp hệ thống. Đây là thiết lập chuẩn cho bất kỳ ai làm việc nghiêm túc với Ruby trên Mac — một khi đã cài xong, việc chuyển đổi giữa Ruby 3.1, 3.2 và 3.3 chỉ cần một lệnh duy nhất.
Bước 1 — Cài rbenv qua Homebrew
# Cài Homebrew trước nếu bạn chưa có
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Sau đó cài rbenv
brew install rbenv ruby-build
Bước 2 — Thêm rbenv vào shell
Với zsh (shell mặc định kể từ Catalina):
echo 'eval "$(rbenv init - zsh)"' >> ~/.zshrc
source ~/.zshrc
Với bash:
echo 'eval "$(rbenv init - bash)"' >> ~/.bash_profile
source ~/.bash_profile
Bước 3 — Cài một phiên bản Ruby
# Xem các phiên bản có sẵn
rbenv install -l
# Cài một phiên bản cụ thể (ví dụ: 3.3.3)
rbenv install 3.3.3
# Đặt làm mặc định toàn cục
rbenv global 3.3.3
Bước 4 — Kiểm tra và cài gem
$ which ruby
/Users/yourname/.rbenv/shims/ruby
$ ruby -v
ruby 3.3.3 (2024-06-12 revision f1a0099d0b) [arm64-darwin23]
# Bây giờ gem install hoạt động không có lỗi
gem install bundler
Cách sửa 2: Dùng Homebrew Ruby trực tiếp
Không cần quản lý nhiều phiên bản Ruby? Chỉ cần cài Ruby qua Homebrew và trỏ PATH vào đó. Ít bước hơn so với rbenv.
brew install ruby
Cấu hình PATH để Ruby của Homebrew được ưu tiên hơn bản hệ thống:
# Apple Silicon (M1/M2/M3/M4)
echo 'export PATH="/opt/homebrew/opt/ruby/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
# Intel Mac
echo 'export PATH="/usr/local/opt/ruby/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
Mở một cửa sổ terminal mới và xác nhận đã có hiệu lực:
$ which ruby
/opt/homebrew/opt/ruby/bin/ruby
$ gem install bundler # Không còn lỗi quyền truy cập
Cách sửa 3: Workaround nhanh — cài vào thư mục home
Cần gem hoạt động ngay bây giờ mà không muốn động vào cấu hình Ruby? Flag --user-install bỏ qua hoàn toàn thư mục hệ thống bằng cách đưa mọi thứ vào ~/.gem thay thế:
gem install bundler --user-install
Các gem được lưu trong thư mục home, nhưng shell sẽ không tìm thấy các file nhị phân của chúng cho đến khi bạn thêm vào PATH:
echo 'export PATH="$(ruby -r rubygems -e "puts Gem.user_dir")/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
Phù hợp cho script cá nhân. Trong một dự án dùng chung với người khác hoặc chạy qua CI, cách này sẽ gây nhầm lẫn — đường dẫn gem của bạn không tồn tại trên máy của họ.
Điều KHÔNG nên làm: tránh sudo gem install
Phản xạ khi gặp lỗi quyền truy cập là thêm sudo vào trước lệnh. Với Ruby gem trên macOS, đó là sai lầm:
- SIP vẫn có thể chặn việc ghi — hoặc cho phép thành công một phần, để lại trạng thái gem bị hỏng.
- Các gem được cài dưới quyền root sẽ gây xung đột sau này khi bạn chuyển sang Ruby do người dùng quản lý.
- Shell của bạn vẫn đang trỏ vào Ruby hệ thống. Nguyên nhân gốc rễ vẫn chưa được giải quyết.
Hãy bỏ qua cách này hoàn toàn.
Xác nhận PATH đang tải đúng
Sau bất kỳ cách sửa nào ở trên, hãy mở một cửa sổ terminal hoàn toàn mới — thoát hẳn và mở lại, không chỉ mở tab mới. Các tab kế thừa phiên shell cũ và sẽ không nhận được cấu hình đã cập nhật của bạn. Sau đó chạy:
$ which ruby
# KHÔNG nên là /usr/bin/ruby
$ gem env home
# Nên trỏ đến đâu đó trong thư mục home hoặc Homebrew prefix của bạn
# ví dụ: /Users/yourname/.rbenv/versions/3.3.3/lib/ruby/gems/3.3.0
$ gem install bundler
# Nên hoàn thành mà không có Gem::FilePermissionError
Mẹo
Để gỡ lỗi quyền truy cập file ngoài lỗi cụ thể này — kiểm tra quyền sở hữu thư mục, xác định giá trị chmod phù hợp, chuyển đổi giữa chế độ số và ký hiệu — Unix Permissions Calculator trên ToolCraft giúp bạn khỏi phải tính toán thủ công. Đáng lưu lại nếu bạn hay phải đoán các giá trị octal.
Khi đã thiết lập rbenv xong, hãy ghim phiên bản Ruby ở cấp độ dự án bằng file .ruby-version:
echo "3.3.3" > .ruby-version
rbenv tự động nhận file này khi bạn cd vào dự án. Mọi người trong nhóm — và CI pipeline của bạn — đều chạy cùng một phiên bản Ruby mà không cần phối hợp gì thêm.
Tóm tắt
- Lỗi xuất phát từ việc cố ghi vào Ruby hệ thống của macOS — Apple khóa nó có chủ ý.
- Cách sửa tốt nhất: cài rbenv hoặc Homebrew Ruby và cập nhật PATH.
- Cách sửa nhanh: dùng
gem install <gem> --user-installđể cài vào thư mục home. - Đừng dùng
sudo gem installtrên macOS — nó né tránh triệu chứng nhưng để nguyên nguyên nhân. - Sau khi sửa, mở terminal mới và chạy
which rubyđể xác nhận bạn đã thoát khỏi/usr/bin/ruby.

