3.3 权限模型:为什么 Homebrew 拒绝 sudo

原文链接: https://docs.brew.sh/FAQ

一句话结论

Homebrew 明确拒绝在 sudo 下工作。遇到任何“请用 sudo 运行 brew”的教程,都应当警惕。

为什么 sudo 是危险的

官方 FAQ 的答案很直白:sudo 很危险,而你当初安装 TextMate.app 时并没有 chown root。意思是:

  • 即使你信任 Homebrew 本身,一次源码构建仍可能执行大量未经 Homebrew 安全审查的上游构建脚本;
  • 以 root 身份运行这些脚本,它们就可以修改或上传操作系统允许访问的任何文件;
  • 历史上确实有构建脚本在配置了其他安装前缀的情况下仍试图修改 /usr。

Homebrew 使用 macOS 沙箱来限制构建脚本,但当进程以 root 运行时,沙箱效果大打折扣(root 几乎可以读写系统上的一切)。所以 Homebrew 宁可拒绝运行,也不愿承担风险。

默认所有权与权限

  • 在 macOS 上,Homebrew 前缀下的所有子目录和文件统一使用 admin 用户组(而不是更弱的默认 staff 组),所有者为执行安装的当前用户。
  • 目录和文件的默认权限是 0755(u=rwx,g=rx,o=rx):只有属主(通常是安装用户)能修改或替换 Homebrew 前缀内的文件,其他用户只能读取和执行。
  • 安装出的二进制运行时以“启动它的用户”的权限执行,而不是以安装者的权限执行。

Homebrew 主要为单用户环境设计,在多用户配置下无法正常工作,官方不支持这种用法。

GUI 应用找不到 brew 安装的命令怎么办

macOS 的 GUI 应用默认不会把 Homebrew 前缀加入 PATH。若某个桌面应用需要调用 brew 安装的工具,可执行:

1
sudo launchctl config user path "$(brew --prefix)/bin:${PATH}"

然后重启电脑。注意这会为所有用户设置 launchctl 的 PATH(详情见 man launchctl)。这条命令中虽然出现了 sudo,但它配置的是系统 launchd 服务,与“用 sudo 运行 brew 命令”是两回事。

日常使用建议

  1. 任何要你把整个 rm -rf /opt/homebrew 或递归 chown/chmod 搬进终端、却不解释清楚后果的“修复方案”,先停一停;
  2. 使用 brew doctor 报告的问题定位具体路径,再修改那一条路径的属主或权限;
  3. 需要以其他用户身份管理系统服务时,优先使用 brew services 或 launchd,而不是给 brew 加 sudo。