修复因 Homebrew 6.0 更新而卡住的 Mac 入职脚本
2026年7月29日
0
Computing/SoftwareRelated Video
5:32Homebrew 6.0 刚改变了 Mac 安装软件的方式
Better Stack
Comments (0)
Log in to leave a comment
No posts yet
5:32Better Stack
Log in to leave a comment
No posts yet
早上刚上班,Slack 上就堆了几十条新员工入职脚本卡住的消息。打开终端一看,发现是在执行 brew install 的过程中,由于一直在等待用户输入而无休止地卡住了。
升级到 Homebrew 6.0 后,交互式界面(Ask mode)与标准输入(stdin)的阻断策略得到了进一步强化。如果是人工手动输入命令倒没什么问题,但如果是通过 Shell 脚本在后台运行,终端就会陷入输入输出的死锁状态。
如果团队成员频繁询问环境配置问题、甚至打断了你自己的工作节奏,你就需要亲自在脚本中写入一些环境变量并做好异常处理了。
Homebrew 6.0 在没有 TTY(交互式终端)连接的状态下安装软件包时,可能会引发意料之外的输入输出等待。要阻止终端挂起并打造一个完美的无人值守运行环境,必须在脚本的最顶端明确声明专用的环境变量。
在脚本最上方添加以下变量后,除了管理员权限请求之外,所有的交互式提示和提示信息(hints)输出都会被关闭。
`bash
#!/usr/bin/env zsh
export NONINTERACTIVE=1
export HOMEBREW_NO_ENV_HINTS=1
export HOMEBREW_ACCEPT_OUTDATED_CAVEATS=1
export HOMEBREW_NO_AUTO_UPDATE=1
export HOMEBREW_NO_INSTALL_CLEANUP=1
if [[ -f "/opt/homebrew/bin/brew" ]]; then
eval "(/usr/local/bin/brew shellenv)"
else
/bin/bash -c "(/opt/homebrew/bin/brew shellenv)"
fi
safe_brew_install() {
local formula="{formula}" &>/dev/null; then
echo "已经安装: {formula}"; then
echo "发生错误: ${formula} 安装失败" >&2
return 1
fi
fi
}
safe_brew_install "git"
safe_brew_install "jq"
`
如果不使用 .zshrc 文件,而是使用 Homebrew 内置配置文件 brew.env 时,需要去掉 export 关键字,仅写成 HOMEBREW_NO_ENV_HINTS=1 这种键值对的形式,这样才不会出现语法错误。
从 6.0 版本开始,出于供应链安全的考量,默认启用了“Tap Trust Model”。未经过验证的外部 Custom Tap 以及使用 MD5、SHA-1 的旧版本软件包将直接被禁止加载。
用于公司内部工具分发的 Formula 必须填写 SHA-256 哈希值,并且需要通过 brew audit --strict 检查,才不会搞砸 CI/CD 流水线。
`ruby
class InternalApiCli < Formula
desc "사내 인프라 API 제어 및 배포 자동화 CLI 도구"
homepage "https://internal.company.net/docs/cli"
url "https://internal.company.net/downloads/cli/v2.4.0/internal-api-cli-2.4.0.tar.gz"
sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
license "Proprietary"
depends_on "jq"
def install
bin.install "internal-api-cli"
end
test do
assert_match "version 2.4.0", shell_output("#{bin}/internal-api-cli --version")
end
end
`
在公司内部分发用的 Formula(internal-api-cli.rb)文件内部,写入符合 SPDX 规范的许可证标识符(license "Proprietary")以及准确的 url 和 desc 字段。如果在 CI/CD 流水线中下载文件后通过 shasum -a 256 提取哈希值,并使用 sed 进行自动更新,就会方便很多。
在开发者的本地 Mac 上执行一次 brew trust company/tools,将公司内部 Tap 注册为受信任源,之后就可以在没有安全警告的情况下直接安装了。
如果 VS Code 终端或旧版终端模拟器是以 Intel(x86_64) 二进制文件运行的,即使使用的是 M 系列 Mac,uname -m 的结果也会显示为 x86_64。在这种状态下安装 Homebrew 软件包,x86 二进制文件会被安装到 /usr/local 下,并报错 mach-o file, but is an incompatible architecture。
因此需要添加条件判断,确认终端环境是否运行在 Rosetta 2 下,并立即重新启动 arm64 原生进程。
`bash
#!/usr/bin/env zsh
SYSTEM_ARCH="(sysctl -n sysctl.proc_translated 2>/dev/null || echo "0")"
if [[ "{SYSTEM_ARCH}" == "x86_64" && "0" "{SYSTEM_ARCH}" == "x86_64" && "${IS_TRANSLATED}" == "0" ]]; then
HOMEBREW_PREFIX="/usr/local"
else
echo "不支持的架构: ${SYSTEM_ARCH}" >&2
exit 1
fi
eval "{HOMEBREW_PREFIX}/bin/brew shellenv)"
`
查询内核参数 sysctl -n sysctl.proc_translated,如果返回 1 则说明处于 Rosetta 2 状态。此时执行 exec arch -arm64 /bin/zsh "$0" "$@",整个脚本就会切换到 arm64 Shell,从而在 /opt/homebrew 路径下安装正确的二进制文件。
如果每个开发者的 Homebrew 版本不同、安装的软件包也不一样,“在我电脑上明明可以”的情况就会不断重复出现。将声明式的 Brewfile 与 brew bundle check 结合并放入脚本中,新入职的人只需执行一行命令就能完成环境配置。
`bash
#!/usr/bin/env zsh
set -euo pipefail
export NONINTERACTIVE=1
export HOMEBREW_NO_ENV_HINTS=1
export HOMEBREW_BUNDLE_NO_UPGRADE=1
DOTFILES_REPO="https://github.com/company/dotfiles.git"
TARGET_DIR="$HOME/.dotfiles"
if ! command -v brew &>/dev/null; then
/bin/bash -c "(/opt/homebrew/bin/brew shellenv)"
fi
if [[ ! -d "{DOTFILES_REPO}" "{TARGET_DIR}" pull origin main
fi
BREWFILE_PATH="{BREWFILE_PATH}" &>/dev/null; then
echo "Brewfile 中的所有依赖项均为最新状态。"
else
brew bundle install --file="${BREWFILE_PATH}"
fi
`
将公司内部 Dotfiles 仓库同步到 $HOME/.dotfiles 后,先通过 brew bundle check 检查是否有未安装的软件包。只有在存在缺失软件包时才执行 brew bundle install,这样即使反复运行脚本多次,也能保持完全一致的环境。