RubyGems 与 Bundler 安装超时怎么办:gem install 卡住、bundle install 报错与镜像配置
写 Ruby 的人几乎每天都要和 RubyGems 打交道:安装 Rails、Jekyll、CocoaPods 要用 gem install,项目依赖要靠 Bundler 按 Gemfile 解析和下载。国内开发者最常遇到的是这几种情况:终端停在「Fetching gem metadata from https://rubygems.org/」不动;等了几分钟后报「Could not fetch specs from https://rubygems.org/ due to underlying error」;或者直接抛出「SSL_connect returned=1 errno=0 state=error: certificate verify failed」。在公司内网、校园网和部分家庭宽带上,这几种报错出现得尤其频繁。
这些报错表面相似,其实分属三类:访问 rubygems.org 本身超时;本机证书链或 OpenSSL 版本过旧导致握手失败;以及网络早已正常、却在编译原生扩展时失败,却被误以为是下载问题。镜像能解决第一类,代理也能解决第一类并且兼顾发布与 GitHub 源,第二、三类则要在本机修。下面先讲各方案的差别,再分步配置。
官方源、镜像与代理的差别
多数人只装依赖,用镜像最省心;但只要你要发布自己的 gem、Gemfile 里引用了 GitHub 仓库,或者镜像刚好没同步到你要的版本,就离不开官方源。实际工作里两者常常并用:日常装依赖走镜像,发布与拉取 Git 源时走线路。
| 对比项 | 官方源直连 | 国内镜像 | 官方源加线路 |
|---|---|---|---|
| 下载速度 | 视网络而定,常超时 | 通常较快 | 取决于节点与出口 |
| 数据新鲜度 | 实时 | 有同步延迟,新版本可能稍晚 | 实时 |
| 发布 gem | 支持 | 不支持,镜像只读 | 支持 |
| Gemfile 改动 | 不需要 | 可用镜像映射,不改文件 | 不需要 |
| GitHub 源依赖 | 常超时 | 镜像不覆盖 | 可一并解决 |
| 团队协作 | 无额外配置 | 每台机器都要配 | 每台机器都要开线路 |
从卡住到装好:分步操作步骤
- 第一步:先把网络线路准备好。需要直连官方源或 GitHub 时,先连上刺猬VPN,再打开终端执行命令。注册只要自定义用户名和密码,不需要邮箱和手机号,免费节点永久免费、不限流量,注册即用。注意终端程序不一定读取系统代理设置,命令仍超时就看第五步;
- 第二步:确认本机环境。执行 ruby -v、gem -v 与 bundle -v,记下版本。Ruby 版本过旧时自带的 OpenSSL 也旧,证书校验失败的根源常在这里,建议用 rbenv 或 asdf 安装当前维护中的版本;
- 第三步:先单独测试网络。执行 gem fetch rake 这类小包下载,几秒内完成说明网络通,问题在别处;长时间无响应才是网络问题;
- 第四步:只装依赖时配置镜像。用 gem sources --add 加入镜像地址,再用 --remove 移除官方源,最后 gem sources -l 确认列表里只剩一个源;Bundler 则用 bundle config mirror.https://rubygems.org 加镜像地址做映射,Gemfile 与锁文件里的源地址保持不变,同事拉代码也不会受影响;
- 第五步:需要走官方源时设置代理环境变量。在终端里设置 HTTPS_PROXY 与 HTTP_PROXY 指向本机代理端口,端口号以你所用工具的设置为准;gem install 也可以用 -p 参数临时指定代理;
- 第六步:执行 bundle install,并加上 --verbose 观察每一步。卡在「Fetching」是网络,卡在「Installing … with native extensions」是编译,两者处理方式完全不同;
- 第七步:处理 Git 源。Gemfile 里写了 git: 或 github: 的依赖由 git 自己下载,不读 Bundler 的镜像配置,需要给 git 单独配置代理,或者确认线路已覆盖终端;
- 第八步:发布自己的 gem。gem push 只能推到官方源,先用 gem signin 登录,热门 gem 的维护者账号要求开启多因素认证,提前在 rubygems.org 的账号设置里绑定好验证器。
按现象排查:网络、证书与编译
排查的关键是看报错停在哪一行。同一条安装命令里,下载、解析依赖、编译、写入四个阶段依次进行,报错信息开头的类名和停住的那一行基本就能告诉你卡在哪个阶段。不要一看到失败就反复重试,网络问题重试十次结果也一样,编译问题更是与网络毫无关系。先把详细输出完整复制下来,再对照下面最常见的现象逐条判断。
- 停在「Fetching gem metadata」几分钟后报 Could not fetch specs:访问官方源超时,配置镜像或开启线路后重试;
- 报 Gem::RemoteFetcher::FetchError 或 Net::OpenTimeout:同属网络超时,检查代理变量是否只在当前终端窗口生效,新开窗口要重新设置;
- 报 certificate verify failed:证书链问题,先升级 Ruby 与 OpenSSL,再执行 gem update --system 更新证书包,不要用关闭校验的办法绕过;
- 报 Failed to build gem native extension:与网络无关,是编译环境缺失,macOS 装 Xcode 命令行工具,Linux 装编译工具链与对应的开发库,nokogiri、pg、mysql2 最常见;
- 镜像里找不到某个版本:镜像同步有延迟,刚发布的版本稍等再装,或临时切回官方源;
- Git 源依赖克隆超时:Bundler 镜像不覆盖 git,单独给 git 配代理;
- 锁文件里的平台不对,部署时报找不到 gem:用 bundle lock --add-platform 补上服务器的平台标识后重新提交锁文件。
常用命令对照
查看当前源用 gem sources -l;清空本地缓存用 gem sources -c;查看 Bundler 生效的全部配置用 bundle config,镜像映射、并发数和安装路径都会列出来;删除镜像映射用 bundle config unset 加对应键名。想让依赖装进项目目录而不是全局,执行 bundle config set --local path 'vendor/bundle',方便在多个项目之间隔离版本。
提速方面,bundle config set jobs 4 可以并行下载与安装;在持续集成环境里,把 vendor/bundle 目录加入缓存,能省掉每次构建的重复下载。这些设置与网络方案相互独立,可以同时使用。
macOS、Linux 与 Windows 的差别
在苹果电脑上,系统自带的 Ruby 版本老旧,而且安装目录受系统保护,直接往里装 gem 会提示没有写入权限。很多人为此加上管理员权限强行安装,结果把系统目录弄乱,后续升级系统时还会出问题。正确做法是用版本管理工具另装一份 Ruby,所有 gem 都装在用户目录下。原生扩展编译需要先装好苹果的命令行开发工具,搭载自研芯片的机型还要注意部分老旧 gem 没有对应架构的预编译包,只能现场编译。
在 Linux 服务器上,发行版仓库里的 Ruby 通常落后好几个版本,建议同样用版本管理工具安装。编译 nokogiri 需要压缩库与 XML 解析库的开发包,连接数据库的 gem 需要对应数据库的客户端开发包,缺哪个报错里都会写明头文件名称,照着装即可。服务器多半没有图形界面,代理变量要写进部署用户的环境配置,不然定时任务和部署脚本仍会超时。
在 Windows 上,推荐使用带开发工具包的 Ruby 安装包,安装时勾选附带的编译环境,否则所有原生扩展都会失败。更省心的做法是在 Windows 的 Linux 子系统里开发,环境与服务器一致,很多兼容问题自然消失。需要注意的是,子系统的网络与宿主机不完全共享,宿主机连上线路后,子系统内的终端未必自动生效,要单独确认代理设置。
团队与持续集成的配置建议
团队里最常见的冲突,是有人在本机把 Gemfile 的源地址直接改成镜像并提交,结果海外的同事和构建服务器全部安装失败。约定好源地址永远写官方源,镜像只用各自机器上的映射配置,这类问题就不会出现。锁文件同理,提交前确认里面的源地址没有被改写。
持续集成环境要看构建机在哪:构建机在境外时直接走官方源最稳定,构建机在国内时在构建脚本开头写入镜像映射。无论哪种,都建议缓存依赖目录,只在锁文件变化时重新安装,这样网络波动对构建的影响会小很多。
长期方案对比
依赖包体积不大,但一个 Rails 项目动辄上百个依赖,频繁的小请求更看重延迟与连接稳定。偶尔装依赖用免费节点即可;每天开发、经常拉 Git 源的,时长套餐更省心。如果你同时在用国内镜像,开启智能分流后镜像请求照常直连,只有官方源与代码托管平台走境外线路,两边互不干扰。实际可用性取决于当前网络环境。
| 对比项 | 免费节点 | 会员节点 | 只用镜像 |
|---|---|---|---|
| 官方源访问 | 多数情况可用 | 延迟更低、波动更小 | 不访问官方源 |
| GitHub 源 | 可用 | 可用 | 不覆盖 |
| 流量规则 | 永久免费、不限流量、不限速 | 时长套餐有效期内不限流量、不限速 | 不涉及 |
| 适合场景 | 偶尔装几个依赖 | 每天开发、频繁拉 Git 源 | 只装公开依赖 |
| 多设备 | 一个账号多设备同时在线 | 一个账号多设备同时在线 | 每台机器单独配置 |
| 分流方式 | 按域名或 IP 智能分流 | 按域名或 IP 智能分流 | 不涉及 |
和其他包管理器的分工
Ruby 生态之外,iOS 开发者还会碰到 CocoaPods——它本身就是一个 gem,装不上 CocoaPods 时先按本文把 RubyGems 修好,再看 CocoaPods 与 Swift Package Manager 访问指南 处理 Specs 仓库与二进制下载。npm、PyPI、Maven、Go 模块等其他包仓库的镜像与代理配置差异,汇总在 开发者包仓库访问指南。
各家包管理器读取代理的方式并不统一:有的读环境变量,有的读自己的配置文件,有的像 git 一样单独设置。遇到「浏览器能开、终端超时」时,先确认这个工具从哪里读代理,再决定改哪里。
常见报错速查表
| 现象 | 原因 | 解决办法 |
|---|---|---|
| Could not fetch specs | 访问官方源超时 | 配置镜像映射或开启线路 |
| Net::OpenTimeout | 终端未走代理 | 设置 HTTPS_PROXY 后重开窗口 |
| certificate verify failed | OpenSSL 或证书包过旧 | 升级 Ruby 并更新 RubyGems |
| Failed to build native extension | 缺编译工具或开发库 | 安装工具链与对应开发库 |
| 镜像找不到新版本 | 镜像同步延迟 | 稍后再装或临时切回官方源 |
| Git 依赖克隆失败 | git 未配置代理 | 单独为 git 设置代理 |
高频问答
- 问:镜像和线路选哪个?答:只装公开依赖选镜像;要发布 gem、拉 GitHub 源或要最新版本时用线路,两者可以并用;
- 问:配了镜像后 Gemfile 要改吗?答:不需要,用 Bundler 的镜像映射即可,锁文件也不会被改写;
- 问:关闭 SSL 校验能解决证书报错吗?答:能绕过但有被篡改依赖的风险,正确做法是升级 Ruby、OpenSSL 与证书包;
- 问:为什么浏览器能打开 rubygems.org,终端却超时?答:终端程序不一定读取系统代理,要在终端里单独设置代理变量;
- 问:持续集成里怎么提速?答:缓存 vendor/bundle 目录并开启并行安装,网络方案按构建机所在地区选择;
- 问:gem push 能推到镜像吗?答:不能,镜像只读,发布只能推到官方源并完成多因素认证。
让依赖安装稳定下来
RubyGems 与 Bundler 安装超时、bundle install 报错,先看报错停在哪:网络问题用镜像或线路,证书问题升级本机环境,编译问题补工具链。把镜像映射写进 Bundler 的全局配置,把代理变量写进终端配置文件,同一台机器以后基本不用再折腾。
刺猬VPN 采用 HTTPS+AES 加密传输,自定义用户名和密码即可匿名注册;免费节点永久免费、不限流量、不限速,适合偶尔装依赖;时长套餐有效期内不限流量、不限速,适合每天开发;客户端支持按域名或 IP 智能分流,国内镜像照常直连,官方源与 GitHub 走境外线路。实际可用性取决于当前网络环境。
换刺猬VPN告别连接烦恼:一键连接、连接稳定
刺猬VPN提供永久免费节点,不限流量;无需邮箱,自定义用户名即可匿名注册。一个账号支持多设备同时在线,实际可用性取决于当前网络环境。