Homebrew `brew update` 卡住问题排查以及解决

发布时间:2026/6/20 7:24:13
Homebrew `brew update` 卡住问题排查以及解决 记一次 Homebrewbrew update卡住镜像源、JSON API 与 Git Tags 的排障环境背景macOS Apple SiliconHomebrew 安装在/opt/homebrewShell 为 zsh网络环境需进行配置优化以访问GitHub等外部资源。问题现象执行brew update终端只输出了如下信息HOMEBREW_BREW_GIT_REMOTE set: using https://mirrors.aliyun.com/homebrew/brew.git as the Homebrew/brew Git remote. Fetching objects: 7之后更新非常慢甚至看起来像卡死。当时已经配置了阿里云 Homebrew 镜像exportHOMEBREW_BREW_GIT_REMOTEhttps://mirrors.aliyun.com/homebrew/brew.gitexportHOMEBREW_CORE_GIT_REMOTEhttps://mirrors.aliyun.com/homebrew/homebrew-core.gitexportHOMEBREW_API_DOMAINhttps://mirrors.aliyun.com/homebrew-bottles/apiexportHOMEBREW_BOTTLE_DOMAINhttps://mirrors.aliyun.com/homebrew/homebrew-bottles后来切到清华 TUNA 后brew update --debug --verbose能成功走完 API 更新阶段Checking if we need to fetch formula.jws.json... Updated formula.jws.json. Checking if we need to fetch cask.jws.json... Updated cask.jws.json. Checking if we need to fetch formula_tap_migrations.jws.json... Updated formula_tap_migrations.jws.json. Checking if we need to fetch cask_tap_migrations.jws.json... Updated cask_tap_migrations.jws.json. Already up-to-date.但brew --version仍然停在Homebrew 5.1.0再次执行普通brew update又出现 Git fetch 错误HOMEBREW_BREW_GIT_REMOTE set: using https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/brew.git as the Homebrew/brew Git remote. error: RPC failed; curl 28 Operation too slow. Less than 1000 bytes/sec transferred the last 20 seconds fatal: protocol error: bad pack header Already up-to-date.这个Already up-to-date很误导。它不代表 Homebrew 主程序已经更新只代表后续update-report阶段没有更多可报告内容。先说结论这次问题不是单纯的“镜像没配好”而是两个问题叠加HOMEBREW_API_DOMAIN/HOMEBREW_BOTTLE_DOMAIN负责 Homebrew JSON API 和 bottle 下载。HOMEBREW_BREW_GIT_REMOTE负责 Homebrew 主程序仓库Homebrew/brew.git的 Git 更新。API 镜像切到清华后已经正常真正让brew版本停留在5.1.0的原因是Homebrew/brew.git 的 git fetch --force --tags origin 没成功因此本地没有拿到5.1.1、6.0.x等新 tag。Homebrew 的 stable 更新逻辑依赖本地已有 tag本地最新 tag 是5.1.0它就只能继续停在5.1.0。最终有效方案是API 和 Bottle 继续走清华镜像Homebrew 主程序brew.git不再走清华/阿里 Git 镜像brew.git改回 GitHub通过优化网络配置如使用HTTP/1.1协议手动刷新 tags删除或注释HOMEBREW_BREW_GIT_REMOTE、HOMEBREW_CORE_GIT_REMOTE避免后续又被强制切回镜像 Git remote。背景知识Homebrew 4 的更新路径变了Homebrew 4.0 之后大多数普通用户不再需要完整克隆homebrew/core和homebrew/cask仓库。Homebrew 默认更多依赖 JSON APIHOMEBREW_API_DOMAIN HOMEBREW_BOTTLE_DOMAIN其中HOMEBREW_API_DOMAIN用于下载 formula/cask 元数据例如formula.jws.json、cask.jws.json。HOMEBREW_BOTTLE_DOMAIN用于下载预编译 bottle。HOMEBREW_BREW_GIT_REMOTE用于更新 Homebrew 自己也就是Homebrew/brew.git。HOMEBREW_CORE_GIT_REMOTE用于本地homebrew/coreGit tap普通用户通常不再需要。清华 TUNA 文档也明确说明brew 4.0 之后大部分用户不需要再克隆homebrew/core只需要设置 API 和 bottle 镜像即可。排障过程1. 确认环境变量是否生效先看当前 Shell 是否真的拿到了 Homebrew 镜像变量printenv|grep^HOMEBREW_当时输出显示变量已经生效HOMEBREW_BREW_GIT_REMOTEhttps://mirrors.aliyun.com/homebrew/brew.git HOMEBREW_CORE_GIT_REMOTEhttps://mirrors.aliyun.com/homebrew/homebrew-core.git HOMEBREW_API_DOMAINhttps://mirrors.aliyun.com/homebrew-bottles/api HOMEBREW_BOTTLE_DOMAINhttps://mirrors.aliyun.com/homebrew/homebrew-bottles所以问题不是/etc/profile完全没生效。2. 确认 Homebrew 自身启动速度正常timebrew--version输出很快Homebrew 5.1.0 brew --version 0.02s user 0.03s system 47% cpu 0.101 total这排除了 Homebrew 自身启动很慢、Ruby 初始化卡住、基础安装损坏等问题。3. 确认没有残留brew/git进程占用锁psaux|grep-E[b]rew|[g]it|[c]url|[r]uby没有发现残留的brew update、git fetch或curl进程。因此不是另一个brew update进程仍在运行。4. 单独测试镜像 Git 仓库是否能连通gitls-remote https://mirrors.aliyun.com/homebrew/brew.git HEAD可以返回01a27a96e15d3bbc02c81b18f95bb1d8f24d490c HEAD这说明“能列远端 HEAD”不等于“能完整git fetch --tags”。后者需要传输 pack对网络、镜像质量及HTTP协议要求更高。5. 用 debug 日志定位brew update卡点执行HOMEBREW_DEBUG1brew update--verbose21|tee/tmp/brew-update-debug.log日志显示API 文件从清华 TUNA 下载成功Checking if we need to fetch formula.jws.json... Updated formula.jws.json. Checking if we need to fetch cask.jws.json... Updated cask.jws.json. Checking if we need to fetch formula_tap_migrations.jws.json... Updated formula_tap_migrations.jws.json. Checking if we need to fetch cask_tap_migrations.jws.json... Updated cask_tap_migrations.jws.json.但 Homebrew 仍然停在5.1.0。关键片段是 git tag --list --sort-version:refname grep -m 1 ^[0-9]*\.[0-9]*\.[0-9]*$ /Library/Developer/CommandLineTools/usr/bin/git tag --list --sort-version:refname UPSTREAM_TAG5.1.0 REMOTE_REFrefs/tags/5.1.0 UPSTREAM_BRANCHstable git checkout --force -B stable refs/tags/5.1.0 git rebase refs/tags/5.1.0 Current branch stable is up to date.这说明 Homebrew 是根据本地 tag 决定 stable 版本的。因为本地最新 tag 只有5.1.0所以它不会升级到更高版本。6. 验证本地 tags 的确缺失git-C$(brew--repo)tag--list5.*--sort-version:refname|head-10修复前看到的最高版本是5.1.0。这就解释了为什么brew --version一直不变。7. 发现git fetch真正失败原因执行普通brew update时出现error: RPC failed; curl 28 Operation too slow. Less than 1000 bytes/sec transferred the last 20 seconds fatal: protocol error: bad pack header这说明git fetch的 HTTP 传输被低速保护中断或者镜像/HTTP 协议链路中途断包导致 Git pack 收到不完整数据进而报bad pack header。最终修复过程3. 取消强制使用 Homebrew Git 镜像unsetHOMEBREW_BREW_GIT_REMOTEunsetHOMEBREW_CORE_GIT_REMOTE把 Homebrew 主仓库 remote 改回 GitHubgit-C$(brew--repo)remote set-url origin https://github.com/Homebrew/brew.git4. 强制用 HTTP/1.1 刷新 main 和 tagsgit-C$(brew--repo)\-chttp.versionHTTP/1.1\fetch--force--tagsorigin refs/heads/main:refs/remotes/origin/main这次成功remote: Enumerating objects: 17951, done. remote: Counting objects: 100% (5036/5036), done. remote: Compressing objects: 100% (58/58), done. remote: Total 17951 (delta 5007), reused 4978 (delta 4978), pack-reused 12915 (from 6) Receiving objects: 100% (17951/17951), 6.64 MiB | 16.66 MiB/s, done. Resolving deltas: 100% (12675/12675), completed with 1135 local objects. From https://github.com/Homebrew/brew 0f7b6e1dd7..01a27a96e1 main - origin/main * [new tag] 5.1.1 - 5.1.1 * [new tag] 5.1.10 - 5.1.10 * [new tag] 5.1.11 - 5.1.11 * [new tag] 5.1.12 - 5.1.12 * [new tag] 5.1.13 - 5.1.13 * [new tag] 5.1.14 - 5.1.14 * [new tag] 5.1.15 - 5.1.15 * [new tag] 6.0.0 - 6.0.0 * [new tag] 6.0.1 - 6.0.1 * [new tag] 6.0.2 - 6.0.25. 验证 tags 已经补齐git-C$(brew--repo)tag--list5.*--sort-version:refname|head-10输出5.1.15 5.1.14 5.1.13 5.1.12 5.1.11 5.1.10 5.1.9 5.1.8 5.1.7 5.1.6这时本地已经具备升级条件。6. 注释镜像 Git remote 配置后brew update正常注释掉# export HOMEBREW_BREW_GIT_REMOTEhttps://mirrors.tuna.tsinghua.edu.cn/git/homebrew/brew.git# export HOMEBREW_CORE_GIT_REMOTEhttps://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-core.git然后在当前 Shell 中执行unsetHOMEBREW_BREW_GIT_REMOTEunsetHOMEBREW_CORE_GIT_REMOTE确认变量为空printenv|grep^HOMEBREW_.*GIT_REMOTE无输出即表示已清理。再次执行brew update输出 Updating Homebrew... Already up-to-date.这次不再出现HOMEBREW_BREW_GIT_REMOTE set: using ... error: RPC failed; curl 28 ... fatal: protocol error: bad pack header最终推荐配置长期不建议保留exportHOMEBREW_BREW_GIT_REMOTE...exportHOMEBREW_CORE_GIT_REMOTE...原因它们会让每次brew update都强制修改 Git remote。本次故障已经证明 Git 镜像链路容易在fetch --tags时失败。Homebrew 4 大多数普通用户不再需要本地homebrew/coreGit tap。推荐只保留 API 和 bottle 镜像exportHOMEBREW_API_DOMAINhttps://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/apiexportHOMEBREW_BOTTLE_DOMAINhttps://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles如果希望避免每次安装软件都触发自动更新可以加exportHOMEBREW_NO_AUTO_UPDATE1推荐的日常命令安装软件时不自动 updateHOMEBREW_NO_AUTO_UPDATE1brewinstallformula手动更新 Homebrew 和 API 元数据brew update如果 GitHub 链路偶发不稳定可尝试调整网络配置并使用 HTTP/1.1GIT_HTTP_LOW_SPEED_LIMIT0\GIT_HTTP_LOW_SPEED_TIME999999\brew update--verbose也可以只给 Homebrew 仓库固定 HTTP/1.1git-C$(brew--repo)config http.version HTTP/1.1常用诊断命令查看 Homebrew 版本brew--version查看 Homebrew 相关环境变量printenv|grep^HOMEBREW_查看是否仍设置了 Git remote 镜像变量printenv|grep^HOMEBREW_.*GIT_REMOTE查看 Homebrew 主仓库 remotegit-C$(brew--repo)remote-v查看本地最新 stable tagsgit-C$(brew--repo)tag--list--sort-version:refname|grep-m10^[0-9]*\.[0-9]*\.[0-9]*$手动刷新 Homebrew 主仓库 main 和 tagsgit-C$(brew--repo)\-chttp.versionHTTP/1.1\fetch--force--tagsorigin refs/heads/main:refs/remotes/origin/main查看 debug 日志HOMEBREW_DEBUG1brew update--verbose21|tee/tmp/brew-update-debug.logtail-80/tmp/brew-update-debug.log误区总结误区 1git ls-remote成功就代表git fetch没问题不是。git ls-remote只需要列远端引用数据量很小。git fetch --tags要下载 pack容易暴露镜像、HTTP/2、低速中断、运营商链路等问题。误区 2Already up-to-date一定代表 Homebrew 已升级不是。这次就出现了Already up-to-date.但brew--version仍然是Homebrew 5.1.0真正要看的是本地 tags 和brew --version。误区 3配置完整镜像变量一定更快不一定。对于 Homebrew 4 普通用户最有价值的是HOMEBREW_API_DOMAIN HOMEBREW_BOTTLE_DOMAIN而HOMEBREW_BREW_GIT_REMOTE HOMEBREW_CORE_GIT_REMOTE可能让brew update在 Git fetch 阶段失败尤其是 Git 镜像同步不完整、网络慢、网络环境不稳定时。根因复盘本次问题的根因链路是配置了HOMEBREW_BREW_GIT_REMOTEbrew update每次都会尝试使用镜像 Git remote 更新Homebrew/brew.git。阿里云 Homebrew API 镜像内容较旧不适合作为当前 Homebrew 5.x 的稳定 API 来源。切到清华后API 下载恢复正常但brew.git的fetch --tags仍在镜像 Git remote 上出现curl 28/bad pack header。因为fetch --tags失败本地最高 stable tag 停留在5.1.0。Homebrew 根据本地最高 tag 选择 stable 版本因此brew --version一直是5.1.0。取消HOMEBREW_BREW_GIT_REMOTE把brew.gitremote 改回 GitHub并通过优化网络配置如使用HTTP/1.1协议成功 fetch tags 后问题解决。最终落地方案最终配置应简化为# Homebrew JSON API 与 bottles 走国内镜像exportHOMEBREW_API_DOMAINhttps://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/apiexportHOMEBREW_BOTTLE_DOMAINhttps://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles# 可选避免安装软件时自动触发 updateexportHOMEBREW_NO_AUTO_UPDATE1不要长期设置# 不建议长期设置# export HOMEBREW_BREW_GIT_REMOTEhttps://mirrors.tuna.tsinghua.edu.cn/git/homebrew/brew.git# export HOMEBREW_CORE_GIT_REMOTEhttps://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-core.git参考资料Homebrew Manpage: https://docs.brew.sh/ManpageHomebrew Common Issues: https://docs.brew.sh/Common-IssuesTUNA Homebrew 帮助: https://mirrors.tuna.tsinghua.edu.cn/help/homebrew/TUNA Homebrew Bottles 帮助: https://mirrors.tuna.tsinghua.edu.cn/help/homebrew-bottles/Git HTTP 配置文档http.lowSpeedLimit/http.lowSpeedTime/http.version总结Homebrew 4 的日常加速重点是 API 和 bottle 镜像不要盲目长期设置HOMEBREW_BREW_GIT_REMOTE。如果brew update卡在 Git fetch先让Homebrew/brew.git回到 GitHub通过优化网络配置如使用HTTP/1.1协议成功刷新 tags再执行brew update。good day