mise Bootstrap Packages 详解:用 [bootstrap.packages] 声明并安装宿主机系统包
【免费下载链接】misedev tools, env vars, task runner项目地址: https://gitcode.com/GitHub_Trending/mi/mise
mise 的[bootstrap.packages]配置段让你把"宿主机原生软件包"(系统库、构建依赖、桌面应用)也纳入声明式管理:在mise.toml中用"manager:package" = "version"的形式列出所需包,再用mise bootstrap packages status/apply/upgrade/prune等命令查询与应用它们。读完本文,你能理解这套机制与 mise 自身[tools]工具管理的分工边界,掌握全部子命令的参数与退出码语义,并了解其背后SystemPackageManagertrait 的多管理器实现,从而在跨平台共享配置、CI 容器初始化等场景中正确使用它。
基本用法:声明与预览
在[bootstrap.packages]中声明共享的宿主包,然后用mise bootstrap packages apply或完整的 mise bootstrap 流程来应用。该机制适用于原生库、构建依赖和宿主应用。
从你机器所用的包管理器开始,Debian/Ubuntu 宿主例如:
[bootstrap.packages] "apt:libssl-dev" = "latest" "apt:build-essential" = "latest"先预览再执行:
mise bootstrap packages status mise bootstrap packages apply --dry-run mise bootstrap packages apply每条条目的键是"manager:package"格式——管理器前缀是必需的;值是一个版本:"latest"表示"装管理器当前能装的版本",或在管理器原生格式支持时写入版本钉(pin,详见各管理器页面,如 apt、brew)。"latest"会接受已安装的任意版本——它不会在每次 apply 时触发升级;升级要用mise bootstrap packages upgrade。
这一点在源码中有对应:PackageRequest 结构体中version字段是Option<String>,注释明确写道"latest"解析为None,各管理器在安装时再把 pin 渲染成各自的原生语法(apt 用name=version,dnf 用name-version)。
按操作系统过滤:table 形式的条目
用 table 形式可以为单个包限定操作系统或 OS/架构。os接受单个值或列表,使用与[tools]相同的名称和别名(linux、macos、windows、linux/x64、macos/arm64等)。省略version时默认为"latest":
[bootstrap.packages] "brew:coreutils" = "latest" "brew-cask:1password" = { os = "macos" } "brew-cask:font-jetbrains-mono" = { os = ["linux", "macos"] } "pacman:libreoffice-fresh" = { state = "absent" } "winget:BurntSushi.ripgrep.MSVC" = { os = "windows" }声明式移除:state = "absent"
pacman条目可以设置state = "absent"来声明式地移除一个包。此时mise bootstrap packages status --missing会把"已安装但配置要求移除"视为漂移,而mise bootstrap packages apply会执行卸载。其他内置管理器目前只支持默认的state = "present"。
源码层面这对应 PackageDesiredState 枚举(Present/Absent);SystemPackageManager::remove 的默认实现直接报错 "{manager}does not support declarative package removal",只有实现了supports_remove()的管理器(即 pacman)才走真实移除路径——这与文档"仅 pacman 支持 absent"的说法完全一致。
brew-cask 的 adopt 选项
brew-cask条目额外接受adopt = true,用于接管已经安装在 cask 目标位置的、内容完全相同的应用(接管而非重装)。设置bootstrap.brew.adopt = true可让接管成为所有 cask 的默认行为,并支持按 cask 用adopt = false覆盖。详见 brew cask 文档。
宿主机包 vs mise 工具:如何选择
| 维度 | [bootstrap.packages] | [tools] |
|---|---|---|
| 版本切换 | 安装结果在项目外共享,切换目录不会切换 | 每个项目可选独立版本 |
| shim | 不创建 shim | 创建 shim 并纳入 PATH |
| 定位 | 属于宿主包数据库/共享 prefix 的软件 | 需要按项目隔离的开发工具 |
宿主包声明在管理器支持时可以带版本约束,但安装是项目外共享的,mise 不为它们创建 shim。需要按项目选择隔离版本时用[tools];软件属于宿主包数据库或共享 prefix 时用[bootstrap.packages]。
管理器列表可通过包管理器插件扩展,覆盖编辑器扩展、其他应用的插件等"宿主拥有的状态"。从源码看,all_managers() 在内置管理器之外加载PluginType::Package类型的插件管理器;插件名与内置管理器冲突时会发出警告并忽略插件。
支持的包管理器
| 管理器 | 平台 | 文档页 |
|---|---|---|
apk | Alpine Linux | apk |
apt | Debian, Ubuntu | apt |
aur | Arch, Manjaro(需 yay 或 paru) | AUR |
dnf | Fedora, RHEL, CentOS, Rocky, Alma | dnf |
pacman | Arch, Manjaro | pacman |
brew | macOS (arm64)、Linux (x86_64/arm64)——无需安装 Homebrew | brew |
brew-cask | macOS;Linux(仅字体类 cask)——无需安装 Homebrew | brew |
flatpak | flatpakCLI 在PATH上的 Linux(system 作用域) | Flatpak |
flatpak-user | flatpakCLI 在PATH上的 Linux(user 作用域) | Flatpak |
mas | masCLI 在PATH上的 macOS | mas |
winget | wingetCLI 在PATH上的 Windows | WinGet |
| plugin | 由插件声明 | Package plugins |
注意 mise 的brew是内置实现而非依赖本机 Homebrew:brew 模块 下有pour.rs、resolve.rs、prefix.rs、cask/等独立子模块,自行解析 formula/cask 元数据并管理自己的 prefix。
语义:合并、过滤与手动执行
- 默认为声明式、累加式——条目按 配置层级(全局 → 项目)做键的并集合并。项目可在全局列表之上追加包(并覆盖全局条目的版本钉);更局部的配置可以用
state = "absent"覆盖一个 pacman 条目。pruning 是显式的、按管理器范围的破坏性操作:mise bootstrap packages prune默认针对 Homebrew,插件拥有的包需要mise bootstrap packages prune --manager <plugin>。它只移除当前配置以及受信任、可加载的 tracked 配置都不再需要的包。 - 按 OS 过滤——
os选择器不匹配的条目、以及当前机器上不可用的管理器对应的条目,都不会被操作,因此同一份配置可以跨平台工作:macOS 上忽略apt条目、Ubuntu 上忽略dnf条目,依此类推。brew在 macOS 和 Linux 上都可用;brew-cask在 macOS 上可用,Linux 上仅支持无生命周期钩子、无结构化安装步骤的字体类 cask;flatpak/flatpak-user在flatpakCLI 位于PATH的 Linux 上可用;mas在masCLI 位于PATH的 macOS 上可用;winget在wingetCLI 位于PATH的 Windows 上可用。status 命令仍会列出不可用的管理器,因此不会有东西被静默隐藏。 - 仅手动安装——mise 从不隐式安装系统包。
mise install在包缺失时只会打印一次性提示;显式的packages apply、packages use和完整的mise bootstrap才执行安装;packages upgrade更新已安装的包。 - 未知管理器带警告忽略,并给出包插件安装提示,因此使用新版 mise 管理器名写的配置在旧版上仍能被解析。
对应源码:src/cli/install.rs 中mise install的缺失提示文案为 "{missing} system package(s) from [bootstrap.packages] are missing. Install them with ...";驱动层在 src/cli/system/driver.rs 中,未配置任何条目时会打印 "no bootstrap packages configured in [bootstrap.packages]"。
命令详解
查询状态:status
mise bootstrap packages status --json mise bootstrap packages status --missingstatus(别名ls)输出 Manager / Package / Installed / State 表格;--json(-J)输出 JSON。--missing在任一配置包未处于期望状态时以退出码 1 退出,可直接用作 CI 检查。
从 SystemStatus 的状态机可以看到完整的状态集合:installed、missing、needs repair、version mismatch、unexpectedly installed(要求 absent 却已安装)、skipped(OS 过滤或不支持当前平台)。被system_packages.managers设置排除的管理器,其条目标记为skipped (excluded by the system_packages.managers setting);管理器不可用时同样逐条列出而非隐藏——这正是文档"nothing is silently hidden"的实现。
应用与记录:apply 与 use
mise bootstrap packages status --json mise bootstrap packages status --missing mise bootstrap packages apply --manager apt --dry-run mise bootstrap packages apply --manager apt mise bootstrap packages apply --update mise bootstrap packages use apt:curl mise bootstrap packages use -g brew:ffmpeg mise bootstrap packages use winget:BurntSushi.ripgrep.MSVC不带包参数的apply读取当前激活的配置;显式请求如mise bootstrap packages apply apt:curl可以不记录到配置就直接安装。若希望包保持声明状态,用use。--update按管理器规则刷新元数据(apk:--update-cache、apt:apt-get update、winget:source update,见 SystemInstall 的参数定义);--yes跳过 mise 的确认提示,但不提供 sudo 凭据。
mise bootstrap packages use就是系统包版的mise use:它把"manager:package" = "version"写入mise.toml(默认本地文件,-g写全局~/.config/mise/config.toml),并安装缺失的部分。对当前机器不可用管理器的条目会只写入不安装——这正是共享配置在 Mac 上写下apt:行的工作方式。
use还有两个实用细节(见 SystemUse):
- 版本钉用
@:mise bootstrap packages use apt:curl@8.5.0-2;不带@(或@latest)则不写 pin。brew formula 与 cask 的@是名称的一部分(如brew:postgresql@17、brew-cask:temurin@17),不是 mise 的版本选择器;mas 用数字 ADAM ID,不支持钉。 - 支持
-e/--env与-p/--path指定写入哪个配置文件;同一包重复出现时后者生效。管理器解析在触碰配置文件之前完成,拼错管理器名不会被写进配置。
导入与清理:import 与 prune
mise bootstrap packages import --manager brew --dry-run mise bootstrap packages import --manager brew mise bootstrap packages prune --manager brew --dry-run不带--dry-run执行前先查看 prune 计划。formula 的清理可能涉及 Homebrew 自身安装的软件,而不仅仅是 mise 安装的。
mise bootstrap packages import --manager brew是 formula 的反向操作:读取 Homebrew 激活的opt链接,把 formula 以"brew:<formula>" = "latest"写入[bootstrap.packages]。默认只导入 keg receipt 表明"应请求安装"的 formula;--all连依赖 formula 一起导入。之后 prune 会保留这些 formula,因为它们已声明在配置中。
mise bootstrap packages prune --manager brew移除不再被当前配置或受信任、可加载的 tracked 配置需要的已链接 brew formula,包括真实 Homebrew 安装的 formula。它是 mise 的声明式清理命令,精神类似于 Homebrew Bundle 的清理(而非上游那个已被 Homebrew 移除的旧brew prune)。
mise bootstrap packages prune --manager brew-cask只移除满足严格条件的 mise 拥有的直接产物:有当前安装时 receipt、内容指纹未变化。它会跳过旧版 receipt、Homebrew 拥有的 cask、pkg 与命令 wrapper 产物、带生命周期动作的 cask、目标已变化或被共享的条目、不完整的安装事务;每条跳过都带原因,且从不应用zap元数据。
对包插件管理器,prune 只考虑 mise 在PackageInstall期间观察到"从缺失变为已安装"的包;已存在或手动安装的包绝不会被接管。插件必须实现PackageUninstall;dry run 只打印批准的移除批次而不调用 hook;mise 在实际移除后用PackageInstalled校验,再更新自己的所有权状态。
升级:upgrade
mise bootstrap packages upgrade --manager apt --dry-run mise bootstrap packages upgrade --manager apt mise bootstrap packages upgrade --manager wingetmise bootstrap packages upgrade刷新包管理器元数据,并把已安装的配置包升级到最新可用版本——apk、apt、dnf 还会遵守配置中的版本钉(AUR、pacman、brew、brew-cask、flatpak、flatpak-user、mas 无法安装钉,pin 条目会被带警告地跳过)。尚未安装的包会被跳过——那是mise bootstrap packages apply的职责。具体行为:brew 会倒入 formula 当前的 bottle 并替换旧 keg;brew-cask 安装当前 cask 产物;flatpak/flatpak-user 在其各自作用域更新已配置的应用与运行时;mas 执行mas upgrade;winget 对每个已配置的已安装包执行精确 ID 的winget upgrade。
这与源码中 SystemPackageManager::upgrade 的默认实现一致:默认upgrade直接复用install(对 brew 恰好正确——倒入不同版本的 formula 即替换旧 keg),apt/dnf/pacman 则重写为先刷新元数据再调用原生 upgrade 命令;SystemUpgrade 也不提供独立--update标志,注释解释了原因:"upgrades refresh metadata themselves (stale lists would make them silent no-ops)"。
另外,mise doctor也会报告已配置的宿主包并在缺失时给出警告。
选择哪些管理器运行
默认情况下,mise 作用于当前机器上所有可用的已配置管理器。可用性检查的是支持平台与必需命令,而不是"选一个首选管理器"。例如一台 Linux 机器若同时声明了 apt 和 mise 内置 Homebrew 管理器,两者都会生效。
当多个管理器都适用(一台机器装了多个包管理器,或共享配置里列出了你不想要这里的管理器),用system_packages.managers设置选子集:
[settings] system_packages.managers = ["apt"]也可以配合上文逐包的os选择器使用。若要把这些选择放进mise.macos.toml或mise.linux.toml,需要用-E/MISE_ENV激活该配置环境,或启用 auto_env;仅凭文件名目前不会激活。
sudo 行为
apk、apt、dnf、pacman 管理器的包变更需要 root,mise 在必要时使用 sudo。AUR 辅助工具以当前用户构建,自行处理安装环节的提权;Flatpak 用户级安装不需要 root。登录 shell 配置需要编辑/etc/shells时走的是同一条 sudo 路径:
- 已是 root(容器、CI):不用 sudo,直接执行命令;
- 交互式终端:例如
sudo apt-get install ...,走正常 sudo 提示; - 非交互且无免密 sudo:mise 报错并打印可手动执行的完整命令——绝不会挂起等待密码;
- 所有情况下,完整命令行在执行前都会记录到日志。
设置system_packages.sudo = false可彻底禁用提权,mise 改为打印命令让你自己执行。Homebrew formula 安装可能需要提权来创建规范 prefix;cask 安装器的产物有时也需要提权(见 brew)。包插件从不使用 mise 的 sudo 路径,也绝不应自行提权。
CI 用法
容器里通常已经是 root,因此不会有提示:
mise bootstrap packages apply --yes mise installmise bootstrap --yes把两者合并(若定义了名为bootstrap的任务,随后还会执行它)——一条命令即可初始化一台新机器或容器。
mise bootstrap packages status --missing在缺包时退出码为 1,可作为一个不安装任何东西的便捷 CI 检查。当必需的管理器可能不可用时,也要检查 JSON 状态输出:被跳过的声明并不能证明其包已安装。
【免费下载链接】misedev tools, env vars, task runner项目地址: https://gitcode.com/GitHub_Trending/mi/mise
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考