6.3 进阶 Brewfile 写法

原文链接: https://docs.brew.sh/Brew-Bundle-and-Brewfile

在受控环境中运行命令

brew bundle exec 会根据 Brewfile 定制一个干净的环境来执行命令:

1
brew "node"
1
brew bundle exec which node

输出会是指向 opt 的真实路径,例如:

1
/opt/homebrew/opt/node/bin/node

它会把 Brewfile 中所有依赖的路径(包括未链接的 keg-only 依赖)都设置好,避免个人 PATH 配置差异。相关子命令:

1
2
3
4
5
brew bundle exec --check    # 执行前先检查依赖是否齐全
brew bundle exec --install  # 执行前先安装缺失依赖
brew bundle exec --services # 执行期间临时启动 Brewfile 中的服务
brew bundle sh              # 进入定制环境的交互 shell
brew bundle env             # 输出所需环境变量,可配合 eval 使用

在 brew bundle exec、brew bundle sh 与 brew bundle env 环境中,HOMEBREW_INSIDE_BUNDLE 会被设为 1,方便脚本检测。

Brewfile 本质上是 Ruby

Brewfile 按 Ruby 求值,因此可以使用 Ruby 逻辑。下面是官方文档提供的一段带注释的示例,覆盖多种实用场景:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# 使用自定义 URL 执行 `brew tap`
tap "user/tap-repository", "https://user@bitbucket.org/user/homebrew-tap-repository.git"

# 设置传给所有 `brew install --cask` 命令的参数
# 例如传 `--appdir=~/Applications` 与 `--require_sha`
cask_args appdir: "~/Applications", require_sha: true

# 为第三方 formula 传选项,例如 `brew install denji/nginx/nginx-full --with-rmtp`
# 安装后还会执行 `brew link --overwrite nginx-full` 与 `brew services restart nginx-full`
brew "denji/nginx/nginx-full", link: :overwrite, args: ["with-rmtp"], restart_service: :always

# 执行 `brew install mysql@5.6`;仅当该 formula 被安装或升级时才重启服务,
# 并执行 `brew link mysql@5.6`;如果装有 mysql,则先 `brew unlink mysql`
brew "mysql@5.6", restart_service: :changed, link: true, conflicts_with: ["mysql"]

# 安装 postgresql@16,若刚安装或升级则运行 postinstall 命令初始化数据目录
brew "postgresql@16",
     postinstall: "${HOMEBREW_PREFIX}/opt/postgresql@16/bin/postgres -D ${HOMEBREW_PREFIX}/var/postgresql@16"

# 安装 ruby 后把版本写入 .ruby-version 文件
brew "ruby", version_file: ".ruby-version"

# 信任 tap、formula 或 cask,使 Homebrew 在要求 tap 信任时也能加载它
tap "user/repository", trusted: true
brew "user/repository/formula", trusted: true
cask "user/repository/cask", trusted: true

# 只信任某个 tap 中指定的 formula、cask 或命令
tap "user/repository", trusted: {
  formula:  "formula",
  casks:    ["cask"],
  commands: ["command"],
}

# 仅在指定操作系统上安装 gnupg(macOS)或 glibc(Linux)
# 注意:由于 Ruby 条件,`brew bundle list` 在其他平台不会输出这些条目
brew "gnupg" if OS.mac?
brew "glibc" if OS.linux?

# 把 cask 安装到自定义应用目录
cask "firefox", args: { appdir: "~/my-apps/Applications" }

# 即使已安装也强制升级 Opera(自更新或 version :latest 类应用)
cask "opera", greedy: true

# 只有系统没有 Java 时才安装 java cask
cask "java" unless system "/usr/libexec/java_home", "--failfast"

# 安装 google-cloud-sdk cask 后运行 gcloud 组件更新
cask "google-cloud-sdk", postinstall: "${HOMEBREW_PREFIX}/bin/gcloud components update"

# 设置环境变量,供 `brew bundle exec` 或 Brewfile 中的 system 命令使用
# 注意:HOMEBREW_PREFIX/bin 默认不在 PATH 中,可在此自行加入
ENV["SOME_ENV_VAR"] = "some_value"

version_file 与 trusted 的补充说明

version_file 适合“项目希望由 Homebrew 安装运行环境、并保持 .ruby-version 等惯例文件同步”的场景。trusted 让声明式信任成为可能,详见 3.4 Tap 第三方仓库与信任模型。

brew bundle dump 会把受信任的整 tap 条目写成 trusted: true,把 tap 中受信任的 formula/cask/命令写成 tap 级信任哈希。每次 brew bundle cleanup 执行后,全局信任库都会被重置为所选 Brewfile 的声明。

新增软件包类型的约束

Homebrew 欢迎为其他包管理器贡献 dump/check/install 支持,但新类型必须满足:

  • 能在无用户交互的情况下安装软件;
  • 能检查软件是否已安装;
  • 能把已安装软件导出为可存入 Brewfile 的格式;
  • 安装不需要 sudo(cask 是例外);
  • 使用范围足够广泛。