macOS 下使用 Ruby Gem 的两个坑

最近需要在自己的 mbp 上用 gem 装俩东西, 然后平了俩坑. 记一下, 作为以后遇到同样问题的记录.

首先是 Connection Reseted 的问题. 症状很简单, 用 gem install 后, 效果如下:

gem install xxx
ERROR: While executing gem ... (Gem::RemoteFetcher::FetchError)
Errno::ECONNRESET: Connection reset by peer - SSL_connect (https://api.rubygems.org/quick/Marshal.4.8/xxx.gemspec.rz)

原因很简单, 在中国 api.rubygems.org 是被墙的, 也不知是什么仇什么怨.

最简单的方法是用淘宝镜像.

淘宝镜像地址是: https://ruby.taobao.org/

淘宝镜像首页说明写得很详细.

淘宝不再维护了。按照重定向，目前可以使用 Ruby China 的。不过按照这尿性….

若是直接用 gem 手工安装的话, 用如下命令即可搞定:

$ gem sources --add https://gems.ruby-china.com --remove https://rubygems.org/
$ gem sources -l
*** CURRENT SOURCES ***

https://gems.ruby-china.com
# 请确保只有 gems.ruby-china.com
# 若发现还有 ruby.taobao.org，可以再删除下:
# $ gem sources --remove https://ruby.taobao.org
$ gem install xxx

它其实就是修改了下你的 ~/.gemrc 文件

若用 bundle , 则可以使用命令

bundle config mirror.https://rubygems.org https://gems.ruby-china.com

在 OS X 下, 若继续 gem install, 那么很容易遇到一个权限类报错，内容如下:

gem install xxx
1 gem installed
gem install xxx
ERROR: While executing gem ... (Gem::FilePermissionError)
You don't have write permissions for the /Library/Ruby/Gems/2.0.0 directory.

原因即字面意思, 就是 gem 要往某个神奇的目录写文件但是你的权限不够. 因为你使用的是 Apple 家自带的 ruby, 在尝试往 Apple 自家的库中塞东西, 默认那个位置是给 root 的.

有两个差劲的方法可以解决这个问题. 一个是前面加 sudo. 这时候记得先用 sudo 重走第一步换个源. 另一种是修改 /Library/Ruby/Gems/2.0.0 这个目录的用户, 即

sudo chown -R $(whoami) /Library/Ruby/Gems/2.0.0

随着版本升级， apple 的系统库也会有所改变。比如 10.14.2 版本的 ruby 是 2.3.0. 这个以此类推即可。

总之就是强行让我们可以写那个目录。但问题是那个库是系统运行时候所用的，要是弄乱了很不好收拾。

个人最建议的是用 homebrew 再装一个 ruby, 这样 local 归 local, system 归 system. 反正也不大。此外，如果自己就更新了系统的 ruby，要是遇到兼容性问题，修改起来很麻烦。

homebrew 的安装方法在官网说得非常详细, 就不赘述了. 稍微提一句, 若是新的用户, 安装完毕后, 需要保证你的环境变量 PATH — 即程序的搜寻路径 — 列表中, /usr/local/bin 的位置是在 /usr/bin 前面的.

通常而言，在 Linux/Unix 系统中，程序使用 PATH 这个环境变量作为搜寻路径列表。这个环境变量用冒号 (colon) 作为有序的多个路径的间隔，每当你输入一个命令的时候，程序都会尝试逐个查询 PATH 中提到的路径，执行第一个包含对应名字的可执行文件。

我们可以简单通过命令 echo $PATH 来查看当前的路径列表。

若没明白也没关系, 你可以考虑安装后先执行下 brew doctor, 它会帮你执行一系列环境相关检查, 对你提出很多建设性的意见. PATH环境变量的问题应该也会有一些相关说明，可以作为进一步的处理介绍。

brew 就绪后，安装 ruby, 一条命令即可:

brew install ruby

然后再 gem 下

$ gem install tmbundle-manager
Fetching: thor-0.19.1.gem (100%)
Successfully installed thor-0.19.1
Fetching: tmbundle-manager-0.1.2.gem (100%)
Successfully installed tmbundle-manager-0.1.2
Parsing documentation for thor-0.19.1
Installing ri documentation for thor-0.19.1
Parsing documentation for tmbundle-manager-0.1.2
Installing ri documentation for tmbundle-manager-0.1.2
Done installing documentation for thor, tmbundle-manager after 1 seconds
2 gems installed

默认情况下, brew 的各种 gems 会装到 /usr/local/lib/ruby/gems/2.3.0 这个位置. 2.3.0 是版本号, 也许在其它位置. 而不是原来的 /Library/Ruby/Gems/2.0.0 这个位置.

完了我们检查下 gem, 发现自带的和系统的完全就用两套库了. 非常好

$ which gem
/usr/local/bin/gem
$ gem list --local

*** LOCAL GEMS ***

bigdecimal (1.2.8)
did_you_mean (1.0.0)
io-console (0.4.5)
json (1.8.3)
minitest (5.8.3)
net-telnet (0.1.1)
power_assert (0.2.6)
psych (2.0.17)
rake (10.4.2)
rdoc (4.2.1)
test-unit (3.1.5)
thor (0.19.1)
tmbundle-manager (0.1.2)

$ /usr/bin/gem list --local

*** LOCAL GEMS ***

activesupport (3.2.19)
bigdecimal (1.2.0)
CFPropertyList (2.2.8)
colored (1.2)
i18n (0.6.11)
io-console (0.4.2)
json (1.7.7)
libxml-ruby (2.6.0)
minitest (4.3.2)
multi_json (1.10.1)
nokogiri (1.5.6)
psych (2.0.0)
rake (0.9.6)
rdoc (4.0.0)
rubygems-update (2.4.2)
sqlite3 (1.3.7)
test-unit (2.0.0.0)
xcodeproj (0.19.4)

补充，关于 PATH 的配置，还是不熟悉，或者对机制感兴趣的，可以参考此处。鸟哥的私房菜可以说是很多小朋友接触终端的启蒙了。而作为 Fedora 粉的我和他的书使用了红帽家的 CentOS 也绝对是大有关系的。