As noted in another comment, the issue isn’t that /usr/bin/gem overwrites any part of Ruby that comes with the system; it doesn’t have permissions to do that under SIP. Instead, it’s installing a new version of rubygems into /Library/Ruby, which takes precedence over the copy in /System if it exists.
I think the underlying problem is that Apple patched the wrong file. Apple patched rubygems/defaults.rb, but that’s a file that comes with rubygems, so it’ll be overridden by a /usr/bin/gem update --system. Rubygems supports customizations via a different file, rubygems/defaults/operating_system.rb. That file isn’t installed by default, but if it exists it always takes precedence over rubygems/defaults; that would have prevented this problem. Homebrew uses that to customize the gem bindir in exactly the same way OS X does.
<willsalz_> r.e. https://lobste.rs/s/tgnykh/how_to_brick_os_x_el_capitan_ruby_gem: the author doesn’t need to ‘reinstall’ the OS they can just ‘upgrade’ over the existing OS and SIP should self-correct. Also a great way to fix other, potentelly messy OS X issues.
Someone on Twitter pointed out to me that this is surprising (and maybe even a bug of sorts): Apparently Apple patches gem in such a way that it doesn’t install binaries to /usr/bin by default any longer.
But that is surprising because your post-update gem was trying to install to /usr/bin. Out of curiosity, what is the default install directory for gems in the defaults file (grep for if defined? RUBY_FRAMEWORK_VERSION):
I’m just wondering if the update to gem overwrote this patch. If so, that seems to be a bug: Apple tried to protect users from this kind of problem, but it should also forbid updating that defaults file.
Update A few people tried the same global gem update and reported that the it installs a new defaults.rb file in /Library/Ruby/Gems. That defaults file is then read before the one patched by Apple, and boom: breakage when gem tries to install to /usr/bin. A relatively easy fix might be to patch the new defaults.rb by hand, so that it matches the Apple patch. It’s trivial change. I mention all this for future Googlers, but it may also help you now. Good luck!
I looked into this, found that the /usr/bin/gem update --system isn’t installing anywhere inside /usr/bin or within the system Ruby at /System; it doesn’t have permissions to do that. Instead, the rubygems update is installing a new rubygems at /Library/Ruby/Site/2.0.0/, which is a sudo-writeable location under SIP; that is loaded by Ruby first before the version that comes with the OS, and it includes a version of rubygems/defaults.rb which lists /usr/bin as the default gem bindir. If you remove /Library/Ruby/Site/2.0.0/rubygems and /Library/Ruby/Site/2.0.0/rubygems.rb, gem will go back to using the original system-installed version and all will be fine; alternately, you can patch /Library/Ruby/Site/2.0.0/rubygems/defaults.rb to change the bindir.
tl;dr: don’t execute commands using sudo unless you know what you are doing. OS X already has some preinstalled gems, upgrading gems or gem itself could result in breakage of software that uses OS X-specific versions. You are basically modifying the base system.
Install Ruby from Homebrew, or even better: use rbenv, rvm, or chruby.
As noted in another comment, the issue isn’t that /usr/bin/gem overwrites any part of Ruby that comes with the system; it doesn’t have permissions to do that under SIP. Instead, it’s installing a new version of rubygems into /Library/Ruby, which takes precedence over the copy in /System if it exists.
I think the underlying problem is that Apple patched the wrong file. Apple patched rubygems/defaults.rb, but that’s a file that comes with rubygems, so it’ll be overridden by a
/usr/bin/gem update --system
. Rubygems supports customizations via a different file, rubygems/defaults/operating_system.rb. That file isn’t installed by default, but if it exists it always takes precedence over rubygems/defaults; that would have prevented this problem. Homebrew uses that to customize the gem bindir in exactly the same way OS X does.From IRC:
I actually had an OS X update pending and applied that, but it didn’t touch gem. Unless they meant something more specific?
Someone on Twitter pointed out to me that this is surprising (and maybe even a bug of sorts): Apparently Apple patches gem in such a way that it doesn’t install binaries to
/usr/bin
by default any longer.But that is surprising because your post-update
gem
was trying to install to/usr/bin
. Out of curiosity, what is the default install directory for gems in the defaults file (grep forif defined? RUBY_FRAMEWORK_VERSION
):/System/Library/Frameworks/Ruby.framework/Versions/<version>/usr/lib/ruby/<version>/rubygems/defaults.rb
I’m just wondering if the update to
gem
overwrote this patch. If so, that seems to be a bug: Apple tried to protect users from this kind of problem, but it should also forbid updating that defaults file.Update A few people tried the same global
gem
update and reported that the it installs a newdefaults.rb
file in/Library/Ruby/Gems
. That defaults file is then read before the one patched by Apple, and boom: breakage whengem
tries to install to/usr/bin
. A relatively easy fix might be to patch the newdefaults.rb
by hand, so that it matches the Apple patch. It’s trivial change. I mention all this for future Googlers, but it may also help you now. Good luck!I looked into this, found that the
/usr/bin/gem update --system
isn’t installing anywhere inside /usr/bin or within the system Ruby at /System; it doesn’t have permissions to do that. Instead, the rubygems update is installing a new rubygems at /Library/Ruby/Site/2.0.0/, which is a sudo-writeable location under SIP; that is loaded by Ruby first before the version that comes with the OS, and it includes a version of rubygems/defaults.rb which lists /usr/bin as the default gem bindir. If you remove /Library/Ruby/Site/2.0.0/rubygems and /Library/Ruby/Site/2.0.0/rubygems.rb, gem will go back to using the original system-installed version and all will be fine; alternately, you can patch /Library/Ruby/Site/2.0.0/rubygems/defaults.rb to change the bindir.Before:
After:
tl;dr: don’t execute commands using sudo unless you know what you are doing. OS X already has some preinstalled gems, upgrading gems or gem itself could result in breakage of software that uses OS X-specific versions. You are basically modifying the base system.
Install Ruby from Homebrew, or even better: use rbenv, rvm, or chruby.
Funny because SIP is in place to prevent you from breaking the base system, even with
sudo
.