mise bootstrap status:一条命令体检整机配置收敛状态,并在 CI 中用 --missing 做漂移检测
2026/9/10 9:20:46 网站建设 项目流程

mise bootstrap status:一条命令体检整机配置收敛状态,并在 CI 中用 --missing 做漂移检测

【免费下载链接】misedev tools, env vars, task runner项目地址: https://gitcode.com/GitHub_Trending/mi/mise

本篇围绕 mise 的mise bootstrap status子命令展开:它是一条只读命令,用于在不做任何变更的前提下,把机器上全部声明式 bootstrap 资源(包、文件、服务、仓库、dotfiles、shell 激活、macOS defaults、systemd 单元等)的当前状态与期望状态汇总成一张报表。读完本文,你将理解它的输出结构、每个标志位的精确语义(尤其是--missing的退出码契约)、它覆盖与不覆盖哪些资源,并能把它接入 CI 作为机器配置漂移的自动化探针。

命令定位:只读的聚合状态检查器

mise bootstrap是 mise 用来应用整台机器设置的工作流:安装[bootstrap.packages]、收敛[bootstrap.files]/[bootstrap.directories]、管理[bootstrap.services]、克隆[bootstrap.repos]、应用[dotfiles]、配置 shell 激活、安装[tools]并执行bootstrap任务。mise bootstrap status则是这个工作流的"只读镜像":

Usage: mise bootstrap status [FLAGS] Aliases: ls Effect: read-only

它的官方描述只有两句话,但信息量很大(见 status.md 与 源码中的文档注释):

Inspect configured resource state without applying changes.--missingsets a nonzero exit status for drift; it does not restrict the listing to missing entries. Dotfile status can render trusted templates, including theirexec()calls.

翻译成三条行为契约:

  1. 只读:status 不会安装任何包、不会克隆仓库、不会写入任何 dotfile,它只比较"配置里声明的期望状态"与"主机上的实际状态";
  2. --missing改的是退出码,不是列表:它不会把输出过滤成只剩缺失项,而是在存在任何漂移时让命令以非零码(1)退出——这正是它成为 CI 探针的基础;
  3. 状态检查可能执行代码:检查 dotfiles 状态时需要把模板渲染出来做比对,受信任(trusted)模板中的exec()函数调用会真实执行。这不是 bug,而是模板比对的必要代价,因此不要在不可信配置上随意运行 status。

基础用法与输出格式

最直接的用法:

mise bootstrap status # 表格输出 mise bootstrap status --json # 机器可读的 JSON mise bootstrap status --missing # 漂移时退出码 1

默认输出是一张四列表格,表头为Part / Item / Current / State(见 run 实现)。若当前配置中没有任何 bootstrap 资源,命令不会报错,只会打印一行nothing configured for bootstrap并以 0 退出——这在 e2e 测试中有明确断言(test_bootstrap)。

一个典型场景:配置了 dotfiles 与工具后,status 会同时列出它们的状态(对应 e2e 断言):

$ mise bootstrap status Part Item Current State dotfiles ~/.gitconfig /…/gitconfig (symlink) applied tools tiny@1.0.0 1.0.0 installed

测试 e2e/cli/test_bootstrap 中验证了三点:表格输出包含dotfiles行、包含tiny@1.0.0且状态为installed--json输出同时包含"dotfiles""tools"键。lsstatus的可见别名(#[usage(visible_alias = "ls)]),因此mise bootstrap ls等效。

--json:结构化输出

-J --json输出一个按部分(part)分组的 JSON 对象,每个部分是一个数组或对象,字段比表格更丰富。从源码的collect_*方法可以确认各部分的结构,例如:

  • tools:每条含toolrequested_versionresolved_versionstateinstalled/missing/unknown/resolve_error)、installed,解析失败时附加error字段(collect_tools);
  • repos:每条含pathurlreforigincurrent_refcurrent_shastatecurrent/missing/differs/dirty/conflict)及reason(collect_repos);
  • packages:按包管理器分组,含available标志;不可用的管理器会输出reason与逐包的skipped状态(collect_packages)。

JSON 模式是编写自动化脚本时的首选入口。

--missing:漂移检测的退出码契约

--missing的语义在文档与实现中完全一致:"if any configured bootstrap state is not in its desired state, exit with code 1"。实现上,BootstrapStatusReport维护一个any_missing布尔量,report.row(...)每次追加一行时以按位或的方式累积缺失标记,最后由run统一裁决:

if self.missing && report.any_missing { return Err(crate::request_exit(1)); }

(src/cli/bootstrap.rs#L3230-L3279)

这意味着退出码的语义是"整个声明面是否全部收敛",粒度覆盖所有被检查的部分。e2e 测试给出了三种典型场景(test_bootstrap):

# 1) 工具未安装(tiny@2.1.0 尚未 mise install) mise bootstrap status --missing # 退出码 1,输出含 tiny@2.1.0 行 mise bootstrap status --json # 含 "state": "missing" # 2) 版本解析失败同样算漂移 # mise.toml 里 tiny = "prefix:9999" 解析不到 mise bootstrap status --missing # 退出码 1,输出含 "resolve error" mise bootstrap status --json # 含 "state": "resolve_error" # 3) 手工伪造的安装不算数:installs 目录里放一个指向其他版本的 # 符号链接,status 仍报告 missing ln -s ./1.0.0 "$MISE_DATA_DIR/installs/tiny/9.9.9" mise bootstrap status --missing # 退出码 1(tiny@9.9.9)

第三条特别值得注意:工具"已安装"的判定走的是 backend 的is_version_installed,runtime 层面的符号链接不会骗过 status——它检查的是真实安装目录。

注意一个边界:--missing只影响退出码,不影响列表内容。缺失与已收敛的行都会照常打印,你需要从 State 列(或 JSON 的state字段)自行区分。

--prompt-secrets:检查前补全缺失的 secret 输入

--prompt-secrets会在检查开始前,对声明了但当前环境中缺失的[bootstrap.secrets]输入发起安全提示(system::secrets::resolve(&config, self.prompt_secrets),见 run 入口)。

为什么 status 需要 secret?因为声明式文件模板、服务通知等内容可能引用 secret 值,status 在解析这些资源时会先经过 secret 校验。不带--prompt-secrets时,缺失的 secret 会以非available状态出现在报表的secret行中,并被计入--missing的漂移判定(collect_secrets把非Available状态标记为 missing,见 collect_secrets)。

覆盖范围:16 个检查面的逐一拆解

collect()方法按固定顺序聚合各部分状态,完整列表可直接从 collect 实现 读出:secrets → packages → accounts → files/directories → services → user services → firewall → compose → repos → dotfiles(含文件与 edit 两类)→ shell activation → macOS defaults → LaunchAgents → systemd units → login shell → tools → plugin 系统依赖。bootstrap 总文档 中"Inspecting state"一节给出了与之一致的叙述:

It reports every declarative part — secrets, accounts, files and directories, services, firewall, Compose projects, packages, repos, dotfiles, shell activation, macOS defaults, LaunchAgents, systemd units, and login shell — plus[tools]and any system dependencies that installed tools require.

各部分在表格中的 State 取值可以从源码归纳如下,这也是读 status 输出的"字典":

Part期望状态漂移状态说明
secretavailable其他非 Available 即计 missing
packagesinstalled(含auto-updates标注)missingneeds repairversion mismatchunexpectedly installed声明"期望缺席"却装着也算漂移;管理器不可用时整组显示skipped (reason)且不计 missing(collect_packages)
accounts / files / services / firewall / composenoopcreate/update/remove统一走资源规划器,action != Noop即 missing(collect_files 等)
reposcurrentmissingdiffersdirty (local changes)conflict (reason)有本地未提交修改的仓库视为漂移(collect_repos)
dotfiles(文件与 edit)appliedtrackedmissingsource missingdiffers (reason)模板条目会先渲染再比对;渲染或检查出错归入differs(collect_dotfiles)
shell(mise-shell-activate)appliedtracked其余按 shell 启动文件中的编辑块检查(collect_shell)
defaults(macOS)setdiffersunset非 macOS 上整组skipped (reason),不计 missing(collect_defaults)
launchd(macOS LaunchAgents)loadedunloadeddiffersmissing平台不可用时同样skipped
systemd(Linux 用户单元)activeinactivediffersmissingdesired(期望启用)为准判定 missing
user(login_shell)setdiffersmissing from /etc/shells检查当前用户登录 shell 与/etc/shells注册(collect_user)
toolsinstalledmissingunknownresolve error (…)不支持当前 OS 的条目直接跳过
plugin-depssatisfiedmissingoptional missing不计检查工具 backend 声明的系统依赖(collect_plugin_deps)

两个从源码结构看值得记住的设计:其一,平台不相关的部分以skipped (reason)呈现且不计入漂移——在 Linux 上检查 macOS defaults 不会让--missing失败;其二,status 复用与 apply 相同的规划逻辑(如request.plan()system::services::plans_with_notifications),因此 status 报告的动作就是 apply 将会执行的动作,两者口径天然一致。

与兄弟命令的分工:status、子部分 status 与 plan

mise bootstrap status是聚合视图;每个部分还有自己的 status 子命令,二者覆盖同一套--missing语义,适合"只关心一块"的场景(bootstrap.md):

mise bootstrap packages status # 只看系统包 mise bootstrap repos status # 只看仓库 mise bootstrap dotfiles status # 只看 dotfiles,支持传目标路径 mise bootstrap mise-shell-activate status mise bootstrap macos defaults status mise bootstrap macos launchd-agents status mise bootstrap linux systemd-units status mise bootstrap firewall status mise bootstrap user status

文档明确建议:mise bootstrap status --missing用一条命令检查整个声明式面;而mise bootstrap packages status --missingmise bootstrap dotfiles status --missing则用于"只想检查某一部分且不安装任何东西"的场合。

mise bootstrap plan的区别值得划清:plan 输出的是声明式资源规划图(accounts、系统包、特权文件目录、服务、防火墙、Compose 项目按依赖序排列),带--detailed-exitcode时退出码为 0=无变化、2=有变化、1=出错或存在unknown资源;status 则面向整机收敛状态,覆盖面更广(含 dotfiles、tools、shell 激活等平台相关项)。preview 完整 apply 流程应使用mise bootstrap --dry-run

实战:在 CI 中做机器配置漂移门禁

综合上述契约,一个典型的"漂移门禁"模式是:

# 在受管机器(或 CI runner 初始化脚本)中 mise trust mise bootstrap --yes # 正常收敛 mise bootstrap status # 人工确认报表 # CI 门禁:任何未收敛即失败 if ! mise bootstrap status --missing; then mise bootstrap status --missing --json # 失败时留下 JSON 现场 exit 1 fi

使用时记住三条边界,它们都能从源码与文档中得到确认:

  1. status 不是快照对比,而是"期望 vs 主机"实时检查:它不关心上一次运行之后的变化,只关心当前主机与当前配置的差;
  2. dotfiles 模板会执行:检查状态需要渲染受信任模板,其中exec()调用真实运行。对不可信的第三方配置,先审查再运行;
  3. 未知项会被显式暴露[tools]中无法解析的版本会报resolve error并计入--missing,不可用的管理器会报skipped (reason)计入漂移——前者是配置错误,后者是平台限制,两者的处理策略不同。

延伸阅读与证据索引

  • 命令参考(本文主体文档):docs/cli/bootstrap/status.md
  • bootstrap 工作流总览(阶段顺序、--only/--skip、hooks、配置分布表):docs/bootstrap.md
  • bootstrap 命令族参考:docs/cli/bootstrap.md
  • 实现:src/cli/bootstrap.rs(BootstrapStatus结构体 L304-L323,run/collectL3259-L3325,各collect_*L3327-L4148)
  • 行为验证:e2e/cli/test_bootstrap(status 输出断言 L33-L38,--missing退出码场景 L80-L97)

【免费下载链接】misedev tools, env vars, task runner项目地址: https://gitcode.com/GitHub_Trending/mi/mise

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询