跳转到主要内容

这是本节的多页打印视图。 .

返回本页常规视图.

Barn 文档

两条命令启动 Barn,再按需查阅管理、配置与命令契约。

Barn 把一份 Pigsty 兼容的 Inventory 启动成固定 IP 的 QEMU 虚拟机。每个 Unix 用户只有一套 deployment,状态位于 ~/.barn,因此生命周期与 SSH 命令可在任意 目录运行。

按任务选择最短路径:

  • 开始使用:两条命令启动第一个实验环境,再按需管理与排障。
  • 参考:Inventory 字段、命令、参数、输出与退出码。
  • 关于:设计、真机验证、已知限制与发布门禁。

新手先按快速上手从源码准备 Barn 0.9.0 发布候选。 CLI 就绪后,用 barn up 启动实验环境,用 barn ssh 进入虚拟机。

重要

Barn 0.9.0 尚未发布。详见发行与验证状态。

1 - 开始使用

用 up 启动 Barn、用 ssh 进入客机,其余管理、排障、镜像、构建与清理按需阅读。

安装 Barn 后,新用户只需按快速上手启动测试环境:

barn up
barn ssh

没有配置文件且没有已有部署时,交互式 up 会生成默认配置;它也能准备缺少的宿主依赖与网络。重复执行 barn up 可重试未完成的客机初始化,不会重启已经健康运行的 VM。无人值守时, 先执行 barn setup --yes,再执行 barn up。

公开软件包状态见当前状态;开发者与源码审查者可使用 从源码构建。

其余内容按任务拆开:

  1. 日常管理:状态、访问、启停、变更、缩容与销毁。
  2. 故障排查:诊断信息与常见问题修复。
  3. 镜像仓库:选择镜像、使用镜像站、导入与清理缓存。
  4. 从源码构建:开发者构建、检查与本地 PATH。
  5. 卸载与清理环境:移除 deployment、镜像、网络与状态。
  6. 自动化与客机脚本:无人值守准备、JSON 验收、可重复执行的客机脚本与 Pigsty 衔接。
  7. 存储与访问:磁盘保留、文件传输、SSH 隧道与 Linux 目录共享。
  8. macOS 虚拟机:尚未发布的 barn mac,在 Apple 芯片上运行带桌面、SSH、 共享目录与剪贴板的 macOS 27 客机。

1.1 - 快速上手

安装 Barn 0.9.0,用 up 启动 Ubuntu 实验环境,用 ssh 进入,再通过同一份配置增量扩容。

安装

通过 Homebrew 安装当前的 Barn 0.9.0 开发版:

brew install --HEAD pgsty/infra/barn
barn version

Homebrew Formula 会从主分支源码构建 CLI 与 hosts 文件 helper。也可以手动从源码构建。

发行包

0.9.0 发行包尚未发布。发布后,用户级安装器支持 macOS/Linux 的 arm64/amd64, 校验归档摘要,安装自身无需 sudo:

curl -fLO https://github.com/pgsty/barn/releases/download/v0.9.0/install.sh
chmod +x install.sh
BARN_VERSION=0.9.0 ./install.sh
export PATH="$HOME/.local/bin:$PATH"
barn version

默认安装目录为 ~/.local/bin;请把相同 PATH 设置写入 Shell 配置。 发行构建应显示 0.9.0。预发布版本不会出现在 GitHub 的 /releases/latest, 请显式设置 BARN_VERSION=0.9.0。

下载问题见下载与 PATH。

发布时还会提供 DEB 与 RPM 包。以下示例使用 amd64;ARM64 使用对应的 linux_arm64 文件。

Debian / Ubuntu
barn_release=https://github.com/pgsty/barn/releases/download/v0.9.0
curl -fLO "$barn_release/barn_0.9.0_linux_amd64.deb"
sudo apt install ./barn_0.9.0_linux_amd64.deb
barn version
RHEL / Fedora
barn_release=https://github.com/pgsty/barn/releases/download/v0.9.0
curl -fLO "$barn_release/barn_0.9.0_linux_amd64.rpm"
sudo dnf install ./barn_0.9.0_linux_amd64.rpm
barn version

下面的宿主要求针对 Linux 客机。macOS 客机使用独立的 barn mac。

宿主要求

宿主 原生加速 最低 QEMU 版本
macOS arm64 / amd64 HVF 8.2.1
Linux amd64 / arm64 KVM 6.2

宿主还需要 qemu-img、OpenSSH 与所选客机对应的固件。交互式 up 可以通过 macOS 的 Homebrew,或受支持 Linux 发行版的 apt/dnf 补齐依赖,并安装固定 IP 网络。宿主软件包与 网络变更可能需要 sudo;Barn 本身应以普通用户运行。Linux 需要可用的 KVM,以及 NetworkManager 或 systemd-networkd。带日期的真机验证覆盖 macOS arm64 与 Ubuntu amd64, 其他构建平台的验证范围较窄,详见当前状态。

启动第一个实验环境

首次部署时,在终端中进入一个空目录:

mkdir -p ~/barn-lab && cd ~/barn-lab
barn up
barn ssh

用 exit 从客机返回宿主终端后,再执行后续 Barn 命令。

没有配置文件、也没有已应用部署时,交互式 up 会生成只有一个 meta 节点的 barn.yml,准备缺少的宿主依赖与网络,下载并校验镜像,启动 QEMU,然后等待管理 SSH 就绪。宿主变更会显示出来,sudo 可能要求输入密码。如果希望先查看完整宿主计划,运行 barn setup --dry-run。

说明

换目录不会新建一套实验环境。状态位于 $BARN_HOME,默认是 ~/.barn。 如果已有部署且当前目录没有配置文件,up 会继续该部署;可先用 barn status 查看。

默认模板解析为:

配置项 默认值
节点 / 固定 IP meta / 10.10.10.10
客机镜像 Ubuntu 24.04,u24:stable,与宿主相同的架构
登录用户 dba,使用 SSH 密钥认证
CPU / 内存 每节点 2 vCPU / 4 GiB
根盘 / 数据盘 64 GiB 根盘 + 挂载到 /data 的 128 GiB 非持久数据盘

磁盘大小是虚拟容量,qcow2 文件随写入增长。四节点环境共配置 8 vCPU、16 GiB 客机内存, 还需为宿主保留资源;启动前可用 barn plan 查看总量。

首次使用、尚未编辑且采用默认网段的内置模板遇到子网冲突时,setup 可以改用可用的私有 /24;若模板文件 已经存在,会备份为 barn.yml.before-network-change。请以生成后的 barn.yml 和 barn status 为准。显式 -f 文件、编辑过的模板与已有部署会保留选定网段。

健康的首次启动会以类似结果结束:

  ✓  1 node ready
connect:   barn ssh meta

barn ssh 默认连接控制节点,在此模板中就是 meta。也可以显式指定节点,或直接执行命令:

barn ssh meta
barn exec meta -- hostname
barn st

st 是 status 的别名; 其中的 running 表示 VM 进程在运行,不代表刚刚重新检查了客机就绪状态。

继续未完成的初始化

重复 barn up 可以接续中断的操作、重试未完成的客机初始化、更新旧的客机脚本。 健康的运行中 VM 会保留进程与根盘。管理 SSH 可用时,即使共享目录只读、私网不可用等功能 受限,客机仍可完成启动。请查看这些提示;自动化应检查 barn up --json 的 nodes[].warnings 与 nodes[].repairs,因为这些限制仍返回退出码 0。

警告

数据盘是可丢弃的测试存储。up 可能清空重建无法识别或确认损坏的文件系统, 包括持久盘,并报告旧数据已丢弃。persistent 只控制 destroy/recreate 时保留磁盘, 不保证恢复时保留损坏的内容。详见数据盘说明。

--no-wait 会跳过客机就绪、恢复与元数据刷新,后续执行 barn up 补齐。 镜像下载支持重试与断点续传;使用 barn up --mirror 优先访问中国官方仓库。 镜像选择与回退规则见镜像仓库。

启动前选择配置

这是前面自动启动流程的另一种入口。在新的实验目录中,先生成并检查配置,再启动:

barn init
barn validate
barn plan
barn up

对于本文使用的 Catalog 镜像,init、validate、plan 都不要求先安装 QEMU 或配置宿主网络。规划已注册的 local-* 镜像时,则需要 qemu-img 校验缓存字节。默认 meta 配置为:

all:
  vars:
    admin_ip: 10.10.10.10
  children:
    nodes:
      hosts:
        10.10.10.10: { nodename: meta }

内置四种模板:

模板 节点数 默认地址
meta 1 10.10.10.10
dual 2 10.10.10.10–10.10.10.11
trio 3 10.10.10.10–10.10.10.12
full 4 10.10.10.10–10.10.10.13

例如 barn init full 生成四节点配置,barn init full -c 10.20.30.0/24 指定另一网段。 现有文件不会被覆盖,除非显式传入 --force。在第一次 up 前调整 vm_cpu、vm_mem、 vm_image 等字段,全部字段见配置参考。

显式准备宿主

setup 只准备依赖与网络,不启动 VM:

barn setup --dry-run
barn setup

与 up 内部的准备流程不同,单独执行 setup 会在应用有变更的计划前请求确认。 它会复用当前目录发现的配置,没有文件时生成 meta。可选的 /etc/hosts helper 仅在 barn hosts install --yes 需要时安装;普通启动与 barn ssh 不依赖这项集成。

下载尊重 HTTP_PROXY、HTTPS_PROXY、ALL_PROXY、NO_PROXY 及其小写形式。 无人值守的首次部署可在空目录执行:

barn setup --yes
barn up --json

setup --yes 本身就能生成配置,只有需要预先编辑时才必须单独 init。自动化环境仍需为 必要的 sudo 操作准备凭据;--yes 不会提供管理员凭据。 自动化教程说明如何保存命令结果、检查客机限制后再继续。

使用现有 Pigsty 配置

barn validate -f pigsty.yml
barn plan -f pigsty.yml
barn up -f pigsty.yml

Barn 读取已记录的 VM、命名与登录字段,其余 Pigsty 参数保持原样。以上步骤启动虚拟机; PostgreSQL 与其他 Pigsty 服务仍需通过 Pigsty 单独安装。内置模板只描述 VM 拓扑, 不包含完整的 Pigsty 服务配置。 衔接方式见自动化与客机脚本, 文件传输与服务连接见存储与访问。

扩容与日常操作

扩展默认单节点环境时,保留已有设置,在 barn.yml 中增加三台主机:

all:
  vars:
    admin_ip: 10.10.10.10
  children:
    nodes:
      hosts:
        10.10.10.10: { nodename: meta }
        10.10.10.11: { nodename: node-1 }
        10.10.10.12: { nodename: node-2 }
        10.10.10.13: { nodename: node-3 }

此例假定使用默认网段;如果 setup 选择了其他网段,所有地址及 admin_ip 都应沿用该网段。 不要为了扩容而用 init --force 覆盖已经定制的配置。

barn plan
barn up
barn st

仅增加这三行时,计划应列出三个待创建节点。up 会创建它们,保留正在运行的 meta 进程,并刷新客机 hosts 与控制节点 SSH 配置。健康的结果为 4 nodes ready。 0.9.0 内置 Catalog 将 u24:stable 解析为 u24@20260926.0.0;手动更新 Catalog 后 可能解析为其他版本,准确版本显示在 plan 和 status 中。

修改 CPU、内存或其他被读取的 VM 字段,需要显式执行 barn recreate <node>; 删除 YAML 条目不会删除 VM。停止并恢复环境,不重建磁盘:

barn stop
barn start

使用完毕后销毁部署:

barn destroy

在终端输入 destroy 确认。根盘与非持久数据盘会被删除,镜像缓存、密钥、声明为持久的 数据盘与宿主网络保留。彻底清理见卸载与清理环境;重启、日志、显式变更与 缩容见日常管理。

barn update 只更新镜像 Catalog。安装 Barn 程序请使用本页开头的 Homebrew 或源码构建方式; 发行包将在 0.9.0 发布后提供。

1.2 - 日常管理

唯一 deployment 的正常生命周期:检查、访问、扩容、变更、停止与销毁。

本教程描述 Barn 0.9.0 发布候选。发布与验收边界见当前状态。

检查与访问

barn status
barn ssh meta
barn exec node-1 -- hostname
barn logs meta --source serial

应用状态默认位于 ~/.barn(可由 BARN_HOME 覆盖),这些命令可在任意目录执行。 切换工作目录不会创建另一套 deployment。 Status 默认显示镜像和资源;--verbose 显示架构、加速器、SSH 端口和 PID, TCG 在普通输出中也明确标记。异常节点不会隐藏其他节点的状态。 barn up 会在选中 VM 启动后,根据完整 applied deployment 重建默认 SSH 别名;因此 局部 up 不会删除未选中节点,可直接运行 ssh meta;如需手工重写,使用 barn ssh-config --install。 plan、up、reload、recreate 依次优先使用 -f、当前目录发现的 Inventory, 两者都没有时才回退到已应用规格;validate 始终需要文件。

再次执行 up 会重试未完成的客机初始化、原位更新旧脚本,健康 VM 无需重启。结果会列出 可选功能限制,JSON/YAML 提供 nodes[].warnings 与 nodes[].repairs。不可用的测试 数据文件系统可能被清空重建,包括持久盘,详见数据盘说明。

停止与启动

barn stop
barn start
barn restart node-1
barn reload -f barn.yml       # 读取并检查配置、停止、收敛

start 启动已停止的 VM 并复查运行中 VM 的就绪状态;start 与 restart 都使用已应用 状态,并刷新 SSH 别名,包括重新分配的自动端口。reload 先读取 Inventory、检查配置变化与启动依赖,再停止选中节点 并执行完整的 up 路径。

up、start、restart、reload、recreate 还会刷新运行中 guest 的 Barn hosts 和控制节点 SSH 条目。--no-wait 跳过就绪检查、客机恢复与 guest 刷新,后续运行 up 补齐。

变更 deployment

barn plan
barn up                         # 创建/启动选中节点,并安装 SSH 别名
barn recreate node-1            # 应用某个节点的 VM 定义变化

plan 规划 Catalog 镜像时无需先准备宿主,展示镜像、资源总量、变更原因与磁盘影响; 规划导入的 local-* 镜像还会校验缓存,需要 qemu-img。CPU/内存等定义 变化仍通过 recreate 应用,会替换根盘与非持久数据盘,持久盘保留。若多个节点同时 变化,局部重建受未选节点影响时会提前拒绝,并列出所需节点。

recreate 与 destroy 在终端上展示磁盘范围并要求输入确认词;--force 跳过提示, 无终端时必须显式传入。

字段 含义 操作
create 配置有、状态无 barn up
recreate VM 定义改变 barn recreate <node>
missing 状态有、配置无 恢复配置,或显式 destroy

删除 YAML 永远不会删除 VM。未消费的 Pigsty 变更得到 action:none;命名与 node-admin 字段虽然不以 vm_ 开头,仍会被消费。成功的 recreate 也会刷新完整 SSH fragment。

并发命令(0.9 候选版)

修改 deployment 的命令会等待其他 Barn 操作释放锁,最长十分钟,同时受命令自身 超时限制。等待信息会显示持锁命令、PID 与开始时间。等待超时返回退出码 4,JSON 为 error: conflict、reason: deployment_busy;持锁操作完成后再重试。 持锁进程退出时锁自动释放;不要通过删除锁文件打断仍在运行的操作。

status、ssh、exec、ssh-config,以及 hosts 读取部署状态的步骤不会排队等待 这把锁,而是读取已写入的状态。其他命令持锁时,status 会附带 note,并且不会 收敛该命令正在进行的状态转换。因此尚在启动中的 VM 可能暂时无法 SSH。

中断恢复见故障排查,脚本处理结果见 自动化。

销毁

barn destroy node-3
barn destroy
barn destroy --delete-persistent
barn destroy --purge
barn purge                         # 无需确认,处置整套实验室

--delete-persistent 与 --purge 只适用于整体销毁,不能和节点选择器一起使用。 --purge 删除持久盘、密钥和 deployment 状态,但保留镜像。节点级 destroy 会刷新 剩余节点的 SSH fragment,整体 destroy 会移除默认 Barn SSH 集成。宿主网络单独卸载, 仍有 VM 挂接时会拒绝。

barn purge 是一次性实验室的简洁路径,等价于 对已有部署执行 destroy --force --purge。它不接受节点选择器,没有 Deployment 时 幂等成功,保留镜像缓存与 宿主网络,同时不会绕过进程身份、属主和路径完整性检查。

**0.9 候选版:**没有 deployment 时,普通 destroy 直接成功。状态已删除但还有 归属明确的持久盘时,使用 purge;destroy --delete-persistent 或 destroy --purge 会提示改用该命令。旧的 rm 别名已移除,必须写出 purge。

barn network uninstall --yes

镜像选择、镜像站与缓存清理见镜像仓库;彻底移除宿主状态见 卸载与清理环境。

1.3 - 故障排查

面向 setup、网络、镜像、漂移、中断状态与 SSH 的简短安全手册。

本页描述 Barn 0.9.0 发布候选。使用版本相关说明前,请先检查 barn version。

先收集诊断信息(status 可能收敛中断的运行时状态):

barn doctor --json
barn network status --json
barn status --json

下载与 PATH 问题

安装器从 GitHub Release 下载程序;--mirror 选择的是 Barn 镜像仓库,不会重定向安装器 下载。如果访问 GitHub 需要代理,在终端将 HTTPS_PROXY 或 ALL_PROXY 设置为已有代理的 地址。macOS 系统代理设置本身不会替命令行工具配置这些环境变量。

用户态安装器默认写入 ~/.local/bin。安装后找不到 barn,或版本仍旧时,检查当前使用的 程序路径:

export PATH="$HOME/.local/bin:$PATH"
command -v barn
barn version

Homebrew 或系统软件包安装应使用对应渠道的程序。CLI 与配套 barn-hosts-helper 应来自 同一 Release,并保留软件包规定的相对位置。

找不到 Inventory

尚无部署时,交互式 up 可以生成首份默认配置。显式使用配置时,在 barn.yml/pigsty.yml 所在目录运行 plan、up、validate, 传入 -f /path/to/file,或运行 barn init 生成一份。状态存在后,plan、up、 reload、recreate 可回退到已应用规格;status、start、stop、SSH 与 destroy 始终使用 已应用状态。如果 status 报告 no deployment state found,说明所选 BARN_HOME 没有已应用部署,可能是首次使用,也可能已执行过 purge。

setup 需要 sudo

提示前一行会说明具体宿主变更;特权步骤开始时 Barn 会直接把交互终端交给 sudo。 --yes 只接受 setup 计划,不会绕过 sudo 认证。自动化环境需要已有凭据或合适的 NOPASSWD 策略。可以先用 barn setup --dry-run 查看计划。

macOS setup 会在请求管理员认证之前准备固定版本的 socket_vmnet 来源,下载失败不会 要求密码。**0.9 候选版:**setup 计划明确说明 sudo 用途与 socket_vmnet 来源;若首次 确认后自动选择的子网改变,会再次确认,除非已经传入 --yes。

原生加速或兼容运行时不可用

原生路径需要 macOS HVF 或 Linux KVM。只有显式外来 vm_arch 或内置镜像/宿主兼容规则 才会选择 TCG;任意原生失败绝不会静默回退。Homebrew QEMU 包含两个 System Emulator; Linux setup 只安装宿主原生家族,因此外来 Guest 还需要对应 qemu-system-* 与固件。

plan 解析 Catalog 镜像及目标运行时时无需安装 QEMU;导入的 local-* 镜像仍需要 qemu-img 与有效缓存。up、recreate 在变更 VM 资源前检查 所选模拟器与固件。TCG 性能结果没有参考意义。

网络是 partial 或 invalid

完整但未激活的 Barn 网络可由交互式 up 恢复;对于 partial 或 invalid 安装, 不要手工删宿主文件,先查看受控清理计划:

barn network status --json --verbose
barn network uninstall --json

未加 --yes 的 JSON 输出只展示删除计划;网络计划仍可能需要 sudo 读取受保护的 归属状态。核对计划后,使用 barn network uninstall --yes 执行。0.9 候选版: 普通终端输出会询问 [y/N],确认后立即执行。Linux bridge smoke 失败会自动回滚安装; 只有出现 automatic rollback failed 才表示必须人工检查。

macOS 的 /var/log/barn-vmnet 缺失或权限过紧时可以修复。查看 network status 的诊断,预期为 root:wheel 0755 目录。barn setup 能修复归属可确认的安装; 手工修复时使用诊断给出的准确命令。符号链接、错误属主或组/其他用户可写目录不会自动 修复。不要仅凭桥接接口名称判断路由冲突。

Linux bridge helper 失败

id
stat -c '%U:%G %a %n' /usr/lib/qemu/qemu-bridge-helper
dpkg-statoverride --list /usr/lib/qemu/qemu-bridge-helper

Debian/Ubuntu 使用 root:<调用者可用组> 4750。桌面系统通过 ACL 获得 /dev/kvm 权限时,调用者不必静态加入 kvm 组。

plan 报 recreate 或 missing

recreate 表示节点定义已改变:先用 barn plan 查看,再运行 barn recreate <node>。 终端上该命令会要求输入 recreate 确认,无终端时必须传入 --force。missing 只是报告: 恢复主机条目,或运行 barn destroy <node>。

节点未就绪

就绪要求管理 SSH 可用且客机实例身份一致。节点无法创建、启动或连接时,节点级部分 失败结果会指出节点和阶段,并以 5 退出。缺少宿主能力、Inventory 冲突等全局失败则使用 各自的退出类别。先查看日志:

barn logs <node>                  # 串口控制台
barn logs <node> --source qemu    # QEMU 诊断
barn logs --source events        # 部署/setup 事件,首次 VM 创建前也可读取
barn status

数据盘、共享目录、主机名、guest hosts、控制节点 SSH 与私网分别初始化,一项失败不会 阻止管理 SSH 或其他步骤。客机可用时返回 0,并列出具体限制;JSON/YAML 通过 nodes[].warnings 暴露这些问题。访问互联网不是就绪的前提。

功能限制 下一步
数据盘不可用 处理设备暂缺、探测、工具、挂载占用或 I/O 问题,再执行 up
共享目录只读 修正宿主权限,再执行 up 重试可写挂载
Guest hosts 或控制节点 SSH 未完成 执行 up 刷新托管文件
私网网卡不可用 检查 barn network status 后再次 up;管理 SSH 仍可能可用

修正原因后重复 up:它会重试未完成步骤、原位更新旧客机脚本、跳过健康步骤,不重启 运行中的 VM。无法识别或确认损坏的测试数据文件系统会自动清空重建,包括持久盘, 结果会报告旧数据已丢弃。探测失败、忙碌挂载和 I/O 故障不会触发格式化。详见 数据盘说明。

重复 up 也可清理能够确认归属的中断准备残留。--rollback 在同一次运行中清除 prepare 失败的产物,并在 rolled_back 中列出。--no-wait 在 QEMU 运行后即返回,跳过就绪检查、 客机恢复与元数据刷新;后续执行 up 补齐。

SSH 失败

Barn 在启动时会从完好的原私钥恢复缺失的部署公钥。若私钥丢失,需要从备份恢复同一把私钥;Barn 不会为已有 VM 生成替代身份。 这是宿主侧派生公钥的恢复,与控制节点中缺失的 Guest 私钥是两种情况。 up 也会检查当前安装的 Guest key:文件缺失时报告 control-ssh 限制,管理 SSH 仍可使用。恢复原 Guest key 后执行 up 会清除限制;向旧 Guest 自动重新注入私钥 仍是待完成的功能。

检查 barn status、barn ssh-config 与串口日志。Barn 自身 SSH 使用回环管理端口; Ansible 直连固定 IP。 若已停止 VM 的自动分配管理端口被其他进程占用,下次启动会选择空闲端口并刷新 SSH 别名; 运行中的 VM 保留原端口。SSH 主机密钥信任按 VM 实例 UUID 区分,重建 VM 无需删除无关的 known-host 条目;同一实例的密钥变化仍会校验失败。

doctor 的通用可用性扫描会排除已应用部署保留的固定 IP;up 与 start 仍会拒绝 已经接受 SSH 的新增节点或已停止节点地址。

0.9 候选版:~/.ssh/config 为符号链接或硬链接时不会被改写;Barn 会生成 fragment,并给出需要通过 dotfile 管理器添加的 Include 行。若 barn ssh meta 可用但 ssh meta 不可用,应先检查 Include,不要更换 Guest 密钥。ssh/exec 会在含数字或 - 的参数匹配近似节点名规则时拒绝执行并给出建议;需要明确区分节点 选择器与远程命令时 使用 --。

Catalog 或镜像校验失败

当前二进制已内置 active 与 standby Catalog 公钥。未知签名者、版本回滚/同版本异内容、 工件尺寸/SHA 不符、qcow2 结构不安全属于不同完整性错误。使用正确签名仓库,或通过 barn image import --sha256 ... 导入;不要直接向 ~/.barn/images 复制字节。

命令被中断

先确认是否仍有其他 Barn 命令运行。0.9 候选版的 status 不排队等待, 其他命令持有部署锁时会读取已写入状态并显示 note。应先等待该命令结束,再判断 中间状态是否属于异常中断。

没有操作持锁时,运行 barn status。可证明存活或死亡的运行时会按记录的完整身份 收敛;歧义进程继续阻塞。不要只凭状态文件里的 PID 就杀进程。

0.9 候选版还支持以下恢复:

中断场景 恢复步骤
宿主重启或 QEMU PID 被复用 status 确认 PID 属于无关进程后将原 VM 标记为停止,再用 start 启动
stop 中断,QEMU 仍在运行 status 恢复运行状态;仍需关机时再次执行 stop
首次 up 在准备阶段失败 修正 Inventory 后再次执行 up -f /path/to/barn.yml,只回滚日志记录的未完成产物
destroy 执行到一半中断 使用相同的显式销毁范围重试;中间状态与已保留的持久盘都可继续处理

如果恢复仍然失败,请保留状态与日志,不要删除节点目录或改写 PID 来模拟恢复成功。

如果记录的 QEMU 进程仍存在,但 QMP Socket 缺失,应先保留证据并查看串口/QEMU 日志, 再决定是否用 stop 收敛。不要手工删除运行时 Socket 或状态文件。

**0.9 候选版:**通用错误信封的 error 字段使用稳定类别,另有可选的 reason、 next 与 command 中的外部程序详情;部分命令返回自身的诊断报告。根据原因与下一步 提示处理,不要把人类可读文本当作 接口解析。退出码与结果处理见自动化。事件与 QEMU 日志按易读记录 展示,需要完整 QEMU 参数时加 --verbose。

提交问题时请包含准确命令与退出码、barn version、上面三份 JSON、宿主系统/架构与 QEMU 版本。

1.4 - 自动化与客机脚本

准备无人值守实验环境,检查 JSON 结果,并在选定客机内运行可重复执行的脚本。

本文示例以 Barn 0.9.0 发布候选为准。 宿主命令应由拥有部署的普通 Unix 用户运行。每次调用使用同一份 Inventory 和 BARN_HOME;切换工作目录不会创建独立实验环境。

准备可预测的实验环境

第一次部署时,先生成并审查配置,再交给自动化运行:

mkdir -p ~/barn-lab
cd ~/barn-lab
barn init dual
# 继续之前先编辑 barn.yml。
barn version
barn validate -f barn.yml
barn plan -f barn.yml
barn setup -f barn.yml --dry-run

将选定的配置纳入版本管理。显式设置 vm_image;如果更新 Catalog 后创建的新节点 也必须使用同一镜像,可固定为 vm_image: u24@20260911.0.0。 显式 -f 还会禁止首次 setup 自动把未编辑的默认模板迁移到其他子网。

审查宿主计划后,执行一次宿主准备:

barn setup -f barn.yml --yes
barn up -f barn.yml --json > up.json

--yes 表示接受 setup 计划,不会提供 sudo 凭据。无人值守执行环境必须提前具备 必要的宿主依赖、网络与权限策略。非交互式 up 不会执行交互式首次宿主准备, up 也没有 --yes 参数。

使用自定义镜像仓库时,setup 与 up 应传入相同的 --repo;规划前先用 barn update --repo URL 显式激活该仓库的 Catalog,详见镜像仓库。

不只检查退出码

Barn 将结构化结果写到 stdout,诊断写到 stderr。保留两种输出与命令退出码, 避免后续 Shell 命令覆盖需要检查的状态。下面是额外依赖 jq 的 Bash 示例:

if barn up -f barn.yml --json > up.json 2> up.stderr; then
  jq -e '
    (.nodes | type == "array" and length > 0) and
    all(.nodes[];
      .state == "running" and .ready == true and
      ((.warnings // []) | length == 0) and
      ((.repairs // []) | length == 0)) and
    ((.warnings // []) | length == 0)
  ' up.json
else
  barn_exit=$?
  cat up.stderr >&2
  cat up.json
  exit "$barn_exit"
fi

此处 jq 要求每个返回节点均已就绪,且没有功能限制或已报告的修复动作。 客机可用但可选数据盘、共享或节点间 SSH 失败时,Barn 仍可能返回退出码 0, 并在 nodes[].warnings 中列出限制。nodes[].repairs 可能报告已丢弃测试数据的 文件系统重置。应根据工作负载选择验收策略,而不是忽略这些字段。顶层 warnings 还可能描述可选 SSH 集成或元数据刷新失败。jq -e 检查失败会向调用方返回非零状态。

下一步依赖客机就绪时,不要使用 --no-wait。status --json 是 VM 状态与缓存警告 的快照,不是新一轮客机就绪测试。用 up 补齐初始化;如果流程依赖某个服务, 还需在客机内执行相应的应用检查。

失败与版本边界

结合命令行退出码与具体命令的结果结构判断。 部分失败可能保留已经成功的节点;重试前查看结果中存在的 nodes 或 failures。

0.9 候选调整了一些错误分类。例如首次缺少配置、未知镜像均为 usage/2; recreate_required 与 nodes_removed 是 conflict/4 下的 reason。 它还使用有上限的锁等待,超时报 deployment_busy。

不是每个失败命令都返回通用的 error/message 信封:doctor、network status、 provision 与 SSH 执行可能返回各自的报告。ssh/exec 透传远程退出状态, 包括 OpenSSH 的 255。结构化执行结果应检查 success、exit_code、stdout 与 stderr,不要把远程退出状态当成 Barn 错误分类。

执行单条命令或脚本

显式指定节点,用 -- 分隔远程命令:

barn exec meta -- hostname
barn exec node-1 -- sh -c 'id; df -h /data'
barn exec meta --json -- uname -a > uname.json

多个客机需要执行相同检查时,将以下 Bash 脚本保存为 check-lab.sh:

#!/usr/bin/env bash
set -euo pipefail
hostname
id
findmnt /data
test -d /data

然后在选定节点运行:

barn provision --script ./check-lab.sh meta node-1
barn provision --script ./check-lab.sh --parallel 2 --timeout 5m --json > provision.json

不带节点选择器时,provision 面向所有已提交节点;这些节点必须已运行。 它不会创建或启动 VM。宿主脚本必须是非空、非符号链接的普通文件,最大 4 MiB。 Barn 将同一份已验证的脚本快照流式传给客机 Bash,记录 SHA-256,不会在客机留下 脚本文件;宿主脚本无需可执行权限。

默认串行执行,--parallel 可设为 1 到 4。--timeout 默认为一小时, 是整个操作的期限,最大 24 小时。--sudo 在客机使用 sudo -n,无法提示输入密码。 结果包含 results[]、各节点 stdout/stderr 与退出码,以及 successful/failed 计数。部分失败时,已经成功的变更可能保留。脚本应允许安全地重复执行;Barn 不会回滚客机命令,也不会在下一次 up 自动重跑该脚本。

provision 同时有成功与失败目标时退出 5;只有一个失败目标时,透传其大于零且不为 255 的远程状态。其他全部失败的情况退出 1,具体客机/SSH 状态见 results[].exit_code。

与 Pigsty 一起使用

Barn 与 Pigsty 可以读取同一份 pigsty.yml,但 barn init dual 只生成 VM 拓扑,不会配置 PostgreSQL 集群。应从当前 Pigsty 仓库合适的服务配置开始并审查:

barn validate -f pigsty.yml
barn plan -f pigsty.yml
barn up -f pigsty.yml
barn ssh

Barn 准备客机管理员与控制节点 SSH 访问。检查配置和客机连通性后,再通过 Pigsty 部署服务。验证记录区分了 Ansible 连通性检查与 完整 Pigsty 安装。宿主文件传输与端口隧道见存储与访问。

1.5 - 存储、文件与服务访问

配置测试数据盘,理解保留规则,传输文件,并通过 OpenSSH 访问客机服务。

本教程使用 Barn 0.9.0 发布候选的接口。执行客机内检查之前, 先完成快速上手。示例使用 meta 节点与默认子网;调整已有配置时, 请沿用实际节点名称与地址。

创建 VM 前选择磁盘

每个节点默认有 64 GiB 根盘,以及挂载到 /data 的 128 GiB 非持久数据盘。 vm_disk 以 GiB 设置根盘大小,vm_disks 替换整个数据盘列表; vm_disks: [] 表示不配置额外数据盘。

新建单节点实验环境时,将以下内容保存为 storage.yml:

all:
  vars:
    admin_ip: 10.10.10.10
    vm_image: u24@20260911.0.0
  children:
    nodes:
      hosts:
        10.10.10.10:
          nodename: meta
          vm_cpu: 2
          vm_mem: 4096
          vm_disk: 64
          vm_disks:
            - {path: /data, size: 64, fs: auto, persistent: true}
            - {path: /scratch, size: 32, fs: ext4, persistent: false}

审查配置,然后创建:

barn validate -f storage.yml
barn plan -f storage.yml
barn up -f storage.yml
barn exec meta -- findmnt /data
barn exec meta -- findmnt /scratch
barn exec meta -- df -h / /data /scratch

size: 64 表示 64 GiB;数据盘也可写成 size: 64GiB。这些是虚拟容量, 不是立即占用的宿主空间;qcow2 文件增长时仍需关注宿主剩余容量。 fs: auto 在客机具备 mkfs.xfs 时优先使用 XFS,否则使用 ext4。 VM 进程启动成功不代表数据盘已挂载,请检查客机结果与警告。

此例用于首次创建。如果同名节点已经存在且定义不同,up 会报告漂移。 检查 plan 并备份所需数据后,才能显式执行 recreate;它会替换根盘与非持久数据盘。

各种操作会保留什么

操作 根盘与非持久数据盘 持久数据盘
stop 后 start,或 restart 保留 保留
健康状态重复 up 保留 保留
规格兼容的 recreate 替换 保留并重新挂载
普通 destroy 删除 保留
整套部署 destroy --delete-persistent 删除 删除,包括已保留的磁盘
整套部署 purge 删除 删除,包括已保留的磁盘

保留盘复用依赖磁盘身份和兼容的规格。再次使用时应保持节点、挂载路径、大小和 文件系统定义一致。它不是自动扩容、改名、文件系统转换、备份或快照功能。 Barn 会拒绝不兼容的保留盘,不要通过手改状态文件强行挂载。

持久盘仍然是可丢弃的测试存储。 客机恢复期间,up 可能清空重建无法识别或 确认损坏的文件系统,并报告数据丢弃。持久性只控制 VM 销毁/重建时的保留行为。 缺少设备、探测失败、挂载点忙碌和 I/O 错误不会触发格式化。 测试故障恢复之前,应将有价值的数据另行保存。

新格式化的数据文件系统由 root 拥有。下面的写入检查使用客机 sudo;应用所需的目录权限 应另行明确配置。在已创建的环境中,可以验证普通重启的数据保留:

barn exec meta -- sudo -n sh -c \
  'printf "retention check\n" > /data/barn-retention.txt'
barn stop meta
barn start meta
barn exec meta -- cat /data/barn-retention.txt

这只检查 VM stop/start,不是物理宿主重启后的持久性验证。 原生验证范围见当前状态。

使用管理 SSH 连接传输文件

从运行中的部署生成独立 OpenSSH 配置:

barn ssh-config > barn-ssh.conf
ssh -F ./barn-ssh.conf barn-meta hostname
scp -F ./barn-ssh.conf ./storage.yml barn-meta:/tmp/storage.yml
scp -F ./barn-ssh.conf barn-meta:/data/barn-retention.txt ./barn-retention.txt

生成的片段包含当前回环 SSH 端口、部署密钥路径与实例主机密钥身份。 重建 VM 或管理端口变化后,应重新生成。如果希望普通 SSH 配置也能使用这些别名, 可选用 barn ssh-config --install;上面的 -F 用法无需这项集成。 导出的配置只引用部署密钥,不会内嵌或导出私钥内容。

访问客机内的服务

宿主可以通过客机固定 IP 访问监听在该地址上的服务,前提是客机防火墙与服务配置允许。 例如 10.10.10.10:5432 上的 PostgreSQL 服务需要另外安装;Barn 启动 VM 不会自动安装 PostgreSQL。

如果服务只监听客机回环地址,可以使用刚才生成的 OpenSSH 配置建立隧道:

ssh -F ./barn-ssh.conf -N \
  -L 127.0.0.1:15432:127.0.0.1:5432 barn-meta

保持该宿主终端打开,再让本地客户端连接 127.0.0.1:15432。 客机服务必须已经监听 5432。Ctrl-C 关闭隧道;如果宿主 15432 已占用,请换一个本地端口。 显式绑定回环地址,使此示例仅供本机访问。

Inventory 没有 vm_ports 或 vm_forwards 字段,未知 vm_* 会被拒绝。 请使用固定 IP 网络或 OpenSSH 转发。管理 SSH 使用独立的回环连接,固定 IP 网络报告限制时,管理连接仍可能可用。

Linux 宿主目录共享

Linux 宿主可以在首次 up 前配置只读共享:

vm_shares:
  - host: /srv/barn-project
    guest: /workspace
    readonly: true

将其放入目标主机变量或 all.vars,把宿主路径替换为已存在、Barn 用户能够访问的 真实目录,而且目录必须属于当前 Barn 用户,只读共享也不例外。 宿主路径必须为绝对路径,不能穿过符号链接,也不能与 Barn 数据根重叠。 源文件共享可以从显式只读开始;可写共享还取决于客机用户权限,Barn 可能回退到 只读并报告限制,不会修改宿主目录属主。

不要在当前文档所述运行时的 macOS 环境中添加 vm_shares。 已测 macOS/QEMU 路径无法重新打开安全持有的目录描述符,受影响节点无法启动;这里应使用 SSH 文件传输。 宿主源目录或挂载丢失时,恢复原目录/挂载后再重试 up;Barn 不会新建空目录替代。 修改已有节点的共享定义需要显式重建。完整磁盘与共享约束见配置参考。

1.6 - macOS 虚拟机

用 barn mac 在 Apple 芯片 Mac 上运行 macOS 27 虚拟机:创建、连接、共享文件与剪贴板,以及清理。
重要

Barn 0.9.0 发布候选,尚未发布。 当前验证结果与发行前检查见 当前状态。请以实际运行的 barn mac --help 为准。

barn mac 在 Apple 芯片 Mac 上创建并运行 macOS 虚拟机。每台机器都是干净、可随时 丢弃的 macOS:带管理员账号、免密 sudo、固定的 SSH 密钥和固定地址,适合测试、构建与复现 macOS 特有的问题。它直接使用 Apple 的 Virtualization 框架,全程不需要管理员权限。

Mac 机器与 Linux 实验环境相互独立:不读取 barn.yml,不加入 Pigsty Inventory, 所有文件都在 $BARN_HOME/mac(默认 ~/.barn/mac)下。Linux 的 destroy 与 purge 不会触碰它们。

前提条件

  • 一台运行 macOS 27 或更高版本的 Apple 芯片 Mac,且已有用户登录桌面。客机同样运行 macOS 27。
  • 第一台机器约需 65 GiB 可用空间:从 Apple 下载的约 25 GiB 恢复镜像(清理前一直保留)、 安装后约 27 GiB 的基础镜像,以及启动所需的余量。此后每台机器按自身改动增长, 上限是磁盘容量,默认 100 GiB。
  • 在正式发布包含 Mac 组件之前,从源码构建需要 Xcode 27。
  • 不需要 sudo:每台机器、它的网络和桌面都以当前用户身份运行。

Apple 规定一台 Mac 上同时最多运行两台 macOS 虚拟机,其他工具的虚拟机和 macOS 安装过程也计算在内。机器可以创建多台,任意两台可以同时运行。

构建 Mac 组件

在包含 barn mac 的 Barn 源码目录中执行:

make mac-build
export PATH="$PWD/bin/mac:$PATH"
barn mac doctor

bin/mac 中包含命令行、Barn Mac.app(运行机器及其桌面的原生组件)和使用说明, 请保持它们放在一起。本地构建使用 ad-hoc 签名。doctor 会检查 macOS 版本、组件与可用空间:

CHECK           RESULT  DETAIL
component       ok      /path/to/barn/bin/mac/Barn Mac.app/Contents/MacOS/barn-mac-runner
virtualization  ok      macOS 27.0.0 on Apple Silicon; virtualization supported
disk            ok      549.8 GiB free
data            ok      no Mac machines yet; barn mac up creates the first

创建第一台机器

barn mac up

这台 Mac 上还没有准备好 macOS 时,up 会先列出需要做的事并请你确认:

→ macOS 27.0 (26A428) is not prepared on this Mac yet.
download:  24.8 GiB from Apple (updates.cdn-apple.com)
then:      install macOS once into a reusable base (about 20 minutes)
free:      551.2 GiB
Download macOS from Apple now? [Y/n]

确认后,Barn 依次:

  1. 只从 Apple 官方下载恢复镜像,并用 Apple 公布的 SHA-256 校验;下载中断后从断点继续。
  2. 一次性安装 macOS,得到一个从未启动过的基础镜像。安装期间会占用两个 macOS 虚拟机名额中的一个。
  3. 创建 mac1:以写时复制的方式克隆基础镜像,启动、创建你的账号,并等到 SSH 与 sudo 可用。
  ✓  mac1 created and ready · macOS 27.0 (26A428) · alice@10.10.20.10
shell:     barn mac ssh mac1
desktop:   barn mac open mac1

之后的每台机器都复用这个基础镜像,几十秒即可就绪;在验证主机上,从已准备好的基础镜像 创建一台机器用时 22 秒。

如果手上已有 Apple 的恢复镜像,可以直接使用,不必重新下载。它与数据在同一个 APFS 卷上时,Barn 以克隆方式引入,不占额外空间;否则校验后原地使用:

barn mac up --ipsw ~/Downloads/UniversalMac_27.0_26A428_Restore.ipsw

没有终端时(例如在脚本中),up 需要 --yes 才会下载,否则直接拒绝,绝不会悄悄下载 25 GiB。barn mac setup 可以提前准备基础镜像而不创建机器。

使用机器

终端与命令

barn mac ssh                                  # 交互式终端
barn mac exec -- sw_vers                      # 执行一条命令
barn mac ssh -- 'id; sudo -n true && echo sudo works'
ProductName:		macOS
ProductVersion:		27.0
BuildVersion:		26A428

账号名与你的 macOS 用户名相同(创建时可用 --user 另选),并拥有免密 sudo。ssh 像普通 ssh 一样把命令行交给客机 shell;exec 保留参数边界。两者都返回客机命令的退出码, --json 会记录标准输出、标准错误与退出码:

barn --json mac exec -- sh -c 'echo out; exit 3'
{
  "command": "exec",
  "node": "mac1",
  "host": "10.10.20.10",
  "arguments": ["sh", "-c", "echo out; exit 3"],
  "success": false,
  "exit_code": 3,
  "stdout": "out\n"
}

以上 JSON 有删节,完整字段见 Mac 命令参考。

桌面

barn mac open

桌面在一个与屏幕大小相称的原生窗口中打开。调整窗口大小时客机分辨率随之改变, View → Enter Full Screen 照常可用。关闭窗口后机器继续运行; 再次执行 open 即可找回窗口,机器已停止时会先启动它。窗口获得焦点时,键盘快捷键都交给客机, 所以宿主侧的操作都放在菜单栏:

菜单 作用
Machine → Share Clipboard 在本次运行中开关剪贴板共享
Machine → Restart… 重启客机中的 macOS
Machine → Shut Down… 正常关机,与 barn mac stop 相同
Window → Keep Running in Background 隐藏窗口,机器继续运行
Barn Mac → Quit Barn Mac… 选择让机器在后台继续运行,或关机

锁屏和桌面中的管理员授权需要登录密码。每台机器的密码随机生成,可以直接复制而不在终端显示:

barn mac password --copy

剪贴板

纯文本随焦点同步:在 Mac 上复制的内容,点进客机窗口后即可粘贴;在客机中复制的内容, 切换到其他应用时同步回 Mac。内容经由这台机器自己的 SSH 连接传输,客机中无需安装任何程序。 被密码管理器标记为敏感的内容不会离开 Mac;图片和文件不会同步。

执行 barn mac configure mac1 --clipboard off 可为某台机器关闭剪贴板共享, 从这台机器下次启动起生效。

共享目录

创建机器时共享 Mac 上的目录,客机把它们挂载在 /Volumes/My Shared Files/<名称>:

barn mac up dev --share ~/src --share docs=~/Documents:ro
barn mac exec dev -- ls "/Volumes/My Shared Files"

名称默认取目录路径的最后一段;:ro 表示只读。共享的必须是已存在的目录,不能是符号链接; Barn 从不创建或删除共享目录。之后要调整共享,先停机再用 configure:

barn mac stop dev
barn mac configure dev --share data=/Volumes/Work/data --unshare docs
barn mac start dev

Mac 修改共享文件后,macOS 客机可能在短时间内仍看到旧内容。需要即时一致的结果时, 请通过 SSH 或 exec 操作。

在其他工具中使用 SSH

第一台机器就绪时,Barn 会在 ~/.ssh/config 中加入一个带标记的 Include。之后 ssh mac1、scp、rsync 以及支持 Remote-SSH 的编辑器都能按名称访问每台机器, 并使用它自己的密钥和固定的主机密钥:

ssh mac1 'uptime'
rsync -a ./project/ mac1:project/
barn mac ssh-config              # 打印这些条目
barn mac ssh-config --remove     # 只移除 Barn 添加的内容

生命周期命令会保持这些条目为最新。若 ~/.ssh/config 是由 dotfile 工具管理的链接, Barn 不会修改它,而是打印需要你手动添加的 Include 行。

多台机器

为每台机器命名。创建参数只对新机器生效:

barn mac up dev --cpu 8 --memory 16G
barn mac ls
NAME  STATE    ADDRESS      SSH    USER   OS          CPU  MEMORY  DISK                 SHARED
dev   running  10.10.21.10  ready  alice  macOS 27.0    8  16 GiB  504.0 MiB / 100 GiB
mac1  running  10.10.20.10  ready  alice  macOS 27.0    4   8 GiB  4.7 GiB / 100 GiB    src
limit:     2 of 2 macOS VMs are running; stop one before starting another

名称使用小写字母、数字和中间连字符,以字母开头。不带名称的命令作用于唯一的一台机器或 mac1;无法确定时会请你指定。DISK 显示机器当前占用的空间与容量。容量属于基础镜像: --disk 与已准备的基础镜像不同时,会先安装另一个基础镜像,这需要再次使用恢复镜像。

每台机器有自己的私有网络:mac1 使用 10.10.20.10,之后的机器依次使用下一个空闲的 /24,并避开局域网、VPN 与 Linux 实验环境。机器可以访问互联网和 Mac,但彼此不通。 已有两台机器在运行时,第三台会在创建任何内容之前被拒绝,并指出可以停止哪一台:

barn mac up build --user ci
error: dev and mac1 are running; macOS allows 2 macOS virtual machines at a time
next: barn mac stop mac1

日常管理

barn mac stop dev               # 通过 macOS 正常关机
barn mac start dev              # 启动并等待 SSH
barn mac restart dev            # 先停再启,使配置变更生效
barn mac stop --all             # 所有机器

stop 执行正常关机;两分钟后仍在运行的机器会被断电,结果中会明确说明。 stop --force 立即断电,相当于长按电源键,客机中未保存的内容会丢失。 start --recovery 启动到 macOS 恢复模式并显示桌面。

up 从不重新配置已有机器。传入与现有配置不同的参数时,它会拒绝执行并给出应使用的命令:

error: dev already exists, so --cpu would not apply; its configuration and data were preserved
next: barn mac configure dev --cpu 4

configure 在机器停止时修改 CPU、内存、共享目录与网络,剪贴板共享可随时修改; 变更从下次启动起生效:

barn mac stop dev
barn mac configure dev --cpu 6 --memory 12G --subnet auto
barn mac start dev

recreate 用基础镜像中全新的 macOS 替换机器,保留名称、账号、资源、共享目录与地址; destroy 删除机器。两者都会先说明将删除的内容,并要求输入命令名确认; 没有终端时用 --force 确认。

barn mac recreate dev
barn mac destroy dev build
操作 客机磁盘与应用 设置、地址与账号
stop/start、restart、重复 up 保留 保留
configure 保留 按要求修改
recreate 换成全新的 macOS 保留;密码与 SSH 密钥重新生成
destroy 删除 删除

以上操作都不会修改共享的基础镜像;删除机器时基础镜像也会保留。

macOS 版本与磁盘空间

barn mac image ls
KIND  OS          BUILD   STATE  ON DISK   CAPACITY  USED BY
base  macOS 27.0  26A428  ready  26.7 GiB  100 GiB   mac1,default

升级总是显式进行。barn mac image update 向 Apple 查询最新的 macOS 27,确认后下载, 并将其设为新机器的基础镜像。已有机器保持原来的 macOS,直到执行 barn mac recreate NAME --update。up 与 start 从不改变机器的 macOS 版本。

image prune 列出没有机器使用、且不是默认的基础镜像,加 --yes 才会删除; --installers 会一并处理已下载的恢复镜像。APFS 克隆共享数据块,因此 ON DISK 与各机器的磁盘数字都不是独占空间,不要相加。

barn mac image prune --installers         # 先查看
barn mac image prune --installers --yes   # 再删除

故障排查

先执行 barn mac doctor:它检查宿主、组件、基础镜像与每台机器,并为每个失败项给出 next: 命令。barn mac logs [名称] 显示机器的运行日志:启动、网络、关机以及 Apple Virtualization 的错误。

现象 处理方法
启动时报 network … overlaps route … VPN 或其他工具占用了该网段。执行 barn mac configure NAME --subnet auto。
macOS allows 2 macOS virtual machines at a time 停止提示中的某台机器,或退出其他工具的 macOS 虚拟机。
第三方 SSH 客户端执行 ssh mac1 报 “No route to host” macOS 的“本地网络”隐私控制阻止了该应用访问私有网络。在系统设置 → 隐私与安全性 → 本地网络中允许它,或改用 /usr/bin/ssh。barn mac ssh 与 exec 始终使用 Apple 自带工具,不受影响。
the Barn Mac component is not installed 或 speaks protocol … 同一次构建的 barn 与 Barn Mac.app 需放在一起;用 make mac-build 重新构建。
通过 SSH 登录 Mac 后启动失败 请在 Mac 桌面会话的终端中运行 barn mac:机器需要已登录用户的会话和已解锁的登录钥匙串。

在虚拟机中登录 Apple 账户并不可靠;不支持 USB 设备、快照和挂起机器。

清理

barn mac destroy --force mac1 dev           # 删除机器
barn mac image prune --installers --yes     # 删除不再使用的镜像

删除最后一台机器时,~/.ssh/config 中的相应条目也会一并移除。默认基础镜像会保留, 供之后创建机器使用;如需删除包括它在内的所有 Mac 文件,先删除全部机器,再删除 $BARN_HOME/mac(默认 ~/.barn/mac)。除该目录外,Barn 只会写入 ~/.ssh/config 中的条目、保存在 ~/Library/Preferences/io.pgsty.barn.mac-runner.plist 中的桌面窗口位置,以及 /tmp 下的一个短路径运行目录。整个过程都不需要 sudo。

1.7 - 镜像仓库

选择 Guest 镜像、使用镜像站、导入本地 qcow2,并清理缓存。

正常使用不需要先执行镜像命令:barn up 默认按本机架构解析 u24:stable,并拉取 最终对应的不可变版本。 Barn 一直使用已安装构建内置的 Catalog,直到你运行 barn update:它会获取、校验并 激活仓库当前的 Catalog;没有任何自动刷新。恢复时可用 image sync 显式激活精确 URL 或文件。

选择镜像

先查看可用别名:

barn image list
barn image info u24
barn image info u24:stable

内置 Family 包括 el7、el8、el9、el10、d12、d13、u22、u24、 u26。裸名称选择 stable,name:channel 选择频道;name@version 优先精确匹配, 较短的数值 Selector 则按点分量边界选择最新匹配版本:

all:
  vars:
    vm_image: el9
    vm_version: "9.7"

这里 9.7 选择最新 9.7.x Build,9 选择最新 9.x Release。若希望跟随仓库可移动的 Stable Channel,则改用 vm_image: el9:stable 并删除 vm_version。独立的 vm_version 不能与 vm_image 中的 :channel 或 @version 同时使用。

修改配置后先运行 barn plan。已有节点的镜像请求改变时,需要显式执行 barn recreate <node>;up 会报告定义漂移而不会自动重建。仅更新 Catalog 不会改变 已有节点或它保存的基础镜像身份。新增或显式重建的节点才会按照活动 Catalog 解析选择器。

需要可重复的实验环境时,应锁定 image info 显示的完整版本,而不是可移动的 Channel 或数值前缀:

all:
  vars:
    vm_image: d13@20260914.2601.2

YAML 中的数值 vm_version 建议加引号,以保留完整原文。

警告

除兼容用途的 EOL el7、EL9 9.3/9.6 与 EL10 10.0 为 deprecated 外, 其余内置版本均为 supported。

使用镜像站

Release 构建默认使用 https://repo.pigsty.io/barn。单条命令可通过仅有长参数的 --mirror 选择中国官方仓库,也可以用 --repo 指定自定义根:

barn image pull u24 --mirror
barn up --mirror
barn update --repo https://mirror.example/barn
barn image pull u24 --repo https://mirror.example/barn
barn up --repo https://mirror.example/barn

或为当前 Shell 设置默认仓库:

export BARN_REPO=https://mirror.example/barn
barn update
barn up

选择优先级依次为 --repo、--mirror、BARN_REPO、全球默认仓库。--mirror 解析为 https://repo.pigsty.cc/barn,两个官方根都保持规范的签名 Catalog 信任。 BARN_REPO 也可以是绝对本地目录。显式本地或 HTTPS 仓库可使用未签名 Catalog;HTTP 仓库必须提供可信密钥签名。文件大小、SHA-256 与 qcow2 结构始终校验。

镜像下载会重试临时故障,并接续中断的传输。选定官方端点无法提供镜像时, 两个官方仓库可以互相回退,仍须匹配同一 Catalog 中的尺寸与摘要。自定义仓库不会回退 到其他站点;Catalog Upstream URL 只用于溯源,始终不是备用下载源。

这项回退只针对镜像工件。barn update 获取选定仓库的 Catalog,image sync 读取 明确指定的 URL 或文件;两者都不会升级 Barn 程序。活动 Catalog 按仓库分别记录。 新 --repo 在激活该根的 Catalog 前使用内置 Catalog;只改变下载源不会让自定义别名出现。

构建静态仓库

仓库只是一个可以直接 rsync 或静态 HTTP 托管的目录:

barn/
├── repo.yaml
├── catalog.json
├── catalog.json.minisig       # 官方与 HTTP 仓库必需
└── images/
    └── d13-1-arm64.qcow2

repo.yaml 是唯一人工维护源。上面单个 arm64 镜像的最小完整配置如下:

schema: 1
revision: 1
defaults: { image: d13, channel: stable, arch: native, boot: uefi }
images:
  d13:
    channels: { stable: "1" }
    versions:
      "1":
        status: testing
        variants:
          arm64:
            source_user: debian

将独立校验且已具备 cloud-init 的镜像放到 /srv/barn/images/d13-1-arm64.qcow2。若是 x86 Guest,文件名与 Variant 都改用 amd64;source_user 应填写镜像的源身份。仓库根必须是绝对路径、非符号链接,且不能 允许组或其他用户写入。在本机生成 catalog.json:

barn repo scan /srv/barn
barn repo build /srv/barn
barn repo verify /srv/barn

scan 只读;build 永不修改 repo.yaml 或镜像字节,它运行完整的 qemu-img check, 并物化文件名、SHA-256、工件大小和虚拟大小。build、verify 需要本机 qemu-img,scan 不需要。在安装 QEMU 的机器上构建后,发布时先上传不可变 QCOW, 最后发布 catalog.json 与匹配签名。本地/HTTPS 示例可以不签名;普通 HTTP 与官方仓库 必须具有可信签名。每次修改 Catalog 内容都应增加 revision。

创建 VM 前,先激活并检查这个本地仓库:

barn update --repo /srv/barn
barn image info d13 --arch arm64 --repo /srv/barn
barn image pull d13 --arch arm64 --repo /srv/barn

plan、up、recreate 都传入相同的 --repo /srv/barn,也可设置 BARN_REPO=/srv/barn。Inventory 中选择 vm_image: d13@1 与 vm_arch: arm64;导入 Catalog 不会改写 Inventory 默认值。 barn image reset --repo /srv/barn 将该根恢复到内置 Catalog,同时保留防回滚记录。

导入与清理

本机原生架构的单个自定义镜像可以直接导入,并提供独立获得的摘要。CLI 中 --sha256 是可选参数;有可信摘要时建议填写:

barn image import --name local-mybase --boot uefi \
  --source-user ubuntu --sha256 <digest> /path/to/base.qcow2

自定义别名必须以 local- 开头;--name、--boot、--source-user 必须一起提供。 导入只检查 qcow2 并复制到 Barn 缓存,不会准备 Guest 软件;镜像必须已经支持 Barn 使用的 cloud-init 初始化。命名导入记录宿主架构,外来架构镜像应使用静态仓库。 在 Inventory 中设置 vm_image: local-mybase,再运行 barn plan。

Prune 会保护选定活动 Catalog 的全部镜像、已应用节点的镜像,以及全部已注册本地别名, 因此销毁所有 VM 后也不会简单清空缓存。删除前先看候选列表:

barn image prune --dry-run
barn image prune --yes

签名、回滚保护、缓存布局、架构与 TCG 规则见镜像参考;准备镜像 Candidate 及发布前的独立验证要求见镜像流水线。

1.8 - 从源码构建

为开发与审查构建 Barn,并运行完整源码检查。

Barn 0.9.0 目前是尚未发布的候选版本。本页用于从源码构建与检查; 正式发布后的安装方式见快速上手。

选择源码

克隆 Barn 源码仓库:

git clone https://github.com/pgsty/barn.git
cd barn

尚未发布时不要假定 v0.9.0 Tag 已存在。构建前核对源码身份与工作区变更, 确认 go.mod 的模块为 github.com/pgsty/barn,命令目录为 cmd/barn:

git log -1 --oneline
git status --short

构建

已审核候选源码的 go.mod 与 packaging/toolchain.env 固定 Go 1.27.1;此外需要 Git、Make、Bash 与标准构建工具。运行 VM 才需要 QEMU 与特权网络准备,编译 CLI 本身不需要。进入选定源码工作区执行:

make build
export PATH="$PWD/bin:$PATH"
barn version

make build 在被 Git 忽略的 bin/ 下生成同一次构建配套的 barn 与 barn-hosts-helper。不要混用来自不同 Commit 或不同 Release 的两个二进制。开发 构建默认显示 dev;Commit 字段显示干净源码的提交,工作区有变更时显示 uncommitted。 不能只凭版本字符串判断是否包含候选功能。

将 Inventory 保存在单独的实验目录。这不会隔离 Barn 状态;已有 deployment 时, 应先检查该部署,再运行 up:

mkdir -p ~/barn-lab && cd ~/barn-lab
barn setup
barn up

完整检查

完整检查还需要 Python 3、jq、供 Race 测试使用的 C 工具链,以及固定版本的质量工具。 安装已审核候选版 CI 所用版本;换用其他源码版本时,重新核对其 CONTRIBUTING.md 与 packaging/toolchain.env:

go install honnef.co/go/tools/cmd/staticcheck@v0.8.1
go install golang.org/x/tools/cmd/deadcode@v0.49.0
go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.13.2
go install golang.org/x/vuln/cmd/govulncheck@v1.7.0

确保 Go 工具安装目录(GOBIN,未设置时为 $(go env GOPATH)/bin)位于 PATH。 提交源码改动前运行:

make check

该门禁包含模块验证、Shell 语法、维护脚本归属、单元与 Race 测试、Vet、Staticcheck、 四目标死代码交集、errcheck、漏洞检查、跨平台构建、镜像流水线和安装器测试、依赖许可证 验证。CI 还单独检查格式、空白、工具准确版本与 GoReleaser 配置;修改打包逻辑还需通过 完整的打包 Snapshot 验证。

通过源码检查不等于已经发布软件包,也不等于完成真机生命周期验证; make image-pipeline-native-test 是独立的真机镜像门禁,需要显式提供 tests/image-pipeline-native-test.sh 开头说明的镜像输入,不会下载测试镜像。

发布工程、依赖许可证与边界说明见工程说明。

1.9 - 卸载与清理环境

安全移除 Barn deployment、集成、镜像、宿主网络与默认状态目录。

本页会删除虚拟机与本地数据。先确认当前状态,不要在仍需保留 Barn VM 时继续:

barn st

1. 删除 deployment

彻底删除节点、持久盘、密钥与 deployment 状态:

barn purge

这条整套处置命令无需确认;镜像缓存与宿主网络仍然保留。若要保留 持久盘或只删除选中节点,继续使用粒度更细且带确认的 barn destroy。

2. 移除可选集成

整体 destroy 已自动移除默认 barn SSH integration。如果使用过自定义 fragment 名称或 /etc/hosts 条目:

barn ssh-config --remove --name lab
barn hosts uninstall --json
barn hosts uninstall --yes

未加 --yes 的 --json 命令只展示 Barn 标记范围内的计划。确认目标正确后再执行 带 --yes 的命令。Barn 0.9.0 的普通终端输出会询问 [y/N],同意后立即卸载。 读取 hosts 计划无需 sudo,实际修改仍需要权限。

3. 删除镜像缓存

barn image prune --dry-run
barn image prune --yes

Prune 删除未引用的缓存镜像与遗留 staging 文件,但会保护已应用 deployment、当前 Catalog 和已注册本地别名引用的镜像,因此不等于清空全部缓存。后面的可选状态目录 清理会一并删除剩余缓存。

4. 卸载宿主网络

barn network uninstall --json
barn network uninstall --yes

第一条 JSON 命令只展示归属明确的删除计划,但可能需要 sudo 读取受保护的网络状态。 只要仍有 VM 接入,网络卸载就会拒绝执行。宿主网络由用户共享;清理自己的部署不代表 其他用户的 VM 也已停止。

5. 清理源码安装残留

宿主网络卸载会保留可独立使用的 hosts helper。仅在确认不再使用 Barn 后,删除下面的准确路径:

sudo rm -f -- /opt/barn/libexec/barn-hosts-helper
sudo rmdir /opt/barn/libexec /opt/barn

若使用默认状态目录,并且前面所有步骤均已完成,可最后删除空余状态:

(
  set -eu
  test -z "${BARN_HOME:-}"
  barn_state_root="$(cd "$HOME" && pwd -P)/.barn"
  test ! -L "$barn_state_root"
  if test -d "$barn_state_root"; then
    printf 'removing exact state root: %s\n' "$barn_state_root"
    find "$barn_state_root" -depth -delete
  fi
)

此段命令在设置了 BARN_HOME 或默认路径为符号链接时停止。自定义状态目录必须 另行核对,不要把目标替换为 $HOME、/、工作区根目录或未经确认的路径。删除后不要 再次运行生命周期命令来验证目录不存在,因为命令可能重新创建锁目录。

QEMU 可能被其他工具共用,默认不要卸载。只有确定没有其他用途时,macOS 才执行:

brew uninstall qemu

检查网络与默认状态目录:

barn network status --json
test ! -e "$HOME/.barn" && echo 'no Barn state'

卸载后的网络预期报告缺失或未就绪,应检查具体结果,不应要求退出码为零。不要把 bridge100 是否消失当作依据:macOS 决定桥接名称,其他软件也可能使用 vmnet 桥。

Archive、Homebrew、DEB 或 RPM 安装的 Barn 二进制应使用对应安装渠道移除;源码构建生成的 bin/ 只是工作区构件,与上述宿主状态无关。

2 - 参考

Barn 读取的 Pigsty Inventory 与命令行的准确契约。

本参考描述 Barn 0.9.0 发布候选。编写脚本前先核对 barn version, 发布进度见当前状态。

  • 配置:发现顺序、变量、默认值、磁盘、共享、命名与漂移。
  • 命令行:命令、关键参数、输出模式与退出码。
  • Mac 命令:尚未发布的 barn mac 的命令、JSON 结果与失败原因。
  • 镜像:签名 Catalog、别名、本地缓存、拉取、导入与清理。
  • 镜像流水线:Candidate 校验与离线归一化。

Barn 不提供受支持的 Go Library API;internal/ 下的包都是实现细节。

2.1 - 配置

Barn 读取的 Pigsty Inventory 字段、默认值与节点级漂移行为。

本参考描述 Barn 0.9.0 发布候选。编写脚本前先核对 barn version, 发布进度见当前状态。

发现顺序

依次查找:显式 -f、当前目录的 barn.yml、barn.yaml、pigsty.yml、 pigsty.yaml。所有文件名都使用同一种 Pigsty 兼容 YAML Inventory。

plan、up、reload、recreate 找不到文件时,如果 deployment 已存在,会回退到 已应用规格;validate 不会回退。配置必须是最大 4 MiB 的普通非符号链接文件。 发现顺序中第一个存在的文件生效;它若无效会直接报错,不会继续尝试下一个文件名。 重命名文件或切换目录不会产生另一套部署,已应用状态保存在 BARN_HOME。

完整配置示例

all:
  vars:
    admin_ip: 10.10.10.10
    vm_image: u24
    vm_cpu: 2
    vm_mem: 4GiB
    vm_disk: 64
  children:
    lab:
      hosts:
        10.10.10.10: { nodename: meta }
        10.10.10.11:
          nodename: worker
          vm_mem: 8GiB
          vm_disks:
            - { path: /data, size: 128, fs: auto, persistent: true }

这里定义了两个托管节点,控制节点为 meta。保存为 barn.yml 后,可以先检查而不启动 VM:

barn validate -f barn.yml
barn --json validate -f barn.yml
barn plan -f barn.yml

JSON 校验结果包含 valid、source、spec_hash、resolved。0.9 候选版本的 validate 还会解析 Catalog 镜像引用,并接受 --repo;Catalog 无法读取时会报告警告, 不会声称镜像已检查;local-* 镜像字节校验仍由 up 完成。配置校验不能证明宿主资源、 共享访问、网络、镜像字节或客机就绪可用,也不会启动 VM 或下载镜像。

Barn 读取什么

Barn 读取主机 IP、nodename、admin_ip、pg_cluster、pg_seq、 node_admin_username、node_admin_uid 与已记录的 vm_* 变量。admin_ip 只从 all.vars 读取,用于选择控制节点;没有匹配时使用第一台托管主机。所有节点必须解析为 同一个登录用户名;默认用户 dba 的显式 node_admin_uid 必须为 88。 自定义用户名下,node_admin_uid 仍需通过整数校验,但不会设置客机 UID;Barn 没有提供任意定制客机 UID 的配置契约。

其余内容完全不读,也不会产生 drift。这里指 pg_role、pg_version、repo_*、 node_packages 等未消费字段,不能泛化为所有 pg_* 或 node_*。

命名空间内严格校验:未知 vm_*、错类型、Jinja 表达式、非法地址、同级分组冲突都会报错。 继承顺序是 all.vars → 更深层的 children.<group>.vars → 主机变量。 主机上的 vm_disks 等列表整体替换继承列表,不会追加。相同深度的组给出不同值时, 必须在主机层覆盖消除冲突。支持 YAML 锚点与合并键:显式键优先,合并序列中靠前的映射优先。 重复映射键和多个 YAML 文档都会报错。

即使 vm_skip: true,主机键也必须是 IPv4 地址。跳过的主机不计入 20 节点上限、也不参与 托管子网推导,但至少要有一台托管主机。跳过已应用节点只会将它标为从配置移除,不会销毁 VM。

0.9 候选版本改进了错误诊断,在可定位时显示规则、错误值、行号,并提示相近的 vm_* 拼写;这些诊断改进没有增加新的 Inventory 变量。

VM 变量

变量 默认值 含义
vm_skip false 不虚拟化这台真实/外部主机
vm_image u24 镜像 Family、Channel 引用或 image@version Selector
vm_version 未设置 匹配 9、9.7 等数值前缀的最新版本
vm_arch native 部署级 Guest 架构:native、amd64 或 arm64
vm_cpu 2 vCPU 数量
vm_mem 4096 MiB 整数,或 8GiB 等尺寸
vm_disk 64 根盘:GiB 整数或 64GiB 等显式尺寸
vm_disks [{path: /data}] 额外数据盘,默认一块挂载到 /data 的 128 GiB 非持久盘
vm_alias [] Guest /etc/hosts、SSH config 与可选宿主别名
vm_shares [] QEMU 9p 宿主目录共享

空主机条目就是一台完整 VM。每套 deployment 支持 1–20 台托管主机;vm_cpu 范围 1–256,内存至少 512 MiB。内存裸整数单位为 MiB,磁盘裸整数单位为 GiB。 显式尺寸字符串支持正整数加 B、KiB、MiB、GiB、TiB、KB、MB、GB、TB (区分大小写)。8GiB 合法,8G、1.5GiB 和无单位的引号字符串 "8192" 不合法。 根盘与数据盘尺寸必须为正值;up 还会检查根盘不小于所选基础镜像的虚拟尺寸。

省略 vm_image 时默认选择 Ubuntu 24.04。使用 Debian 13 时,在 all.vars 中 写明 vm_image: d13;修改已有 Barn 配置后先查看 barn plan。

vm_version 将简短的版本意图与镜像 Family 分开:

vm_image: el9
vm_version: 9.7

Catalog 中存在完全相同的版本时优先精确匹配;否则只在点分量边界匹配,并选择数值语义上 最新的结果:9.7 选择最新 9.7.* Build,9 选择最新 9.x Release。各分量按整数 比较,因此 9.10 晚于 9.9。vm_version 不能与已经带 :channel 或 @version 的 vm_image 同时使用。

vm_arch 比普通逐主机字段更严格:出现时必须在所有托管主机上解析为同一个值,因此 应只在 all.vars 定义一次。修改它属于 deployment envelope 变化,必须整体重建。 Linux setup 只安装宿主原生模拟器;外来架构还需要对应 qemu-system-* 与固件。

数据盘

vm_disks:
  - path: /data
    size: 128
    fs: auto
    persistent: false

path 同时是磁盘身份与挂载点;fs 为 auto(默认)、xfs 或 ext4。空白的 auto 磁盘在 guest 有 mkfs.xfs 时格式化为 XFS,否则为 ext4,与 Vagrant 流程的 行为一致;显式 xfs、ext4 不会降级,健康的已有文件系统直接复用。persistent: true 在普通 destroy 后保留;vm_disks: [] 表示不要额外盘。每项 size 默认 128 GiB, 整数单位为 GiB,也接受显式尺寸字符串。

挂载点需是 /data、/data/pg 等规范绝对路径。磁盘身份由路径去除首尾 /,再把中间的 / 替换为 -,必须匹配 [a-z][a-z0-9-]{0,31};单个节点内磁盘身份与挂载点均不得重复。 /、/etc、/usr、/root、/var/lib/barn 等系统路径及与它们重叠的父子路径会被拒绝。 修改持久盘身份或声明可能需要显式迁移;persistent 不表示任意新定义都能自动复用旧盘。

数据盘按可丢弃的测试存储处理。 up 会将无法识别或确认损坏的文件系统清空重建为 配置的类型,并报告旧数据已丢弃。这同样适用于 persistent 盘:持久性控制销毁、重建 VM 时是否保留盘,不保证保留损坏内容。探测失败、设备暂缺、挂载占用或底层 I/O 故障不会 触发格式化;系统盘和宿主共享目录不属于此恢复范围。

目录共享

macOS 限制: Barn 的目录身份保护共享方式尚不支持 macOS,配置了 vm_shares 的节点无法启动;候选版本还会在 validate、plan 时发出警告。新建 macOS 实验环境 应先省略共享;完整共享支持仍待完成。修改已有节点的共享配置需要 recreate,会替换 根盘,请先保留所需数据。Barn 不会退回未经身份校验的宿主路径。

vm_shares:
  - host: /absolute/owned/source
    guest: /src
    readonly: true

readonly 默认为 true,每个节点最多八个共享。宿主与客机路径必须是规范绝对路径, 不会展开 ~ 或相对路径。源目录必须已经存在、属于调用者,路径的任何分量都不能是 符号链接,也不能与 BARN_HOME 重叠。Linux 上请优先使用真实路径(realpath /path/to/source);0.9 候选版本 会在符号链接错误中提示应该填写的真实路径。

同一节点内宿主源目录、客机目标目录均不得相互重叠;不同节点只有全部只读时才允许宿主 源目录重叠。客机目标不能覆盖数据盘挂载点、保留系统路径或登录用户的 .ssh 目录。 9p 只适合可信开发文件,不能放 PostgreSQL 数据。 请求可写共享但客机无法写入时,Barn 尝试只读访问并报告限制;修正权限后再次 up 即可重试。Barn 不会递归修改宿主文件的属主。

Barn 的 up、start 会将源目录缺失的影响限制在对应节点,其余选中节点 继续执行。恢复原目录或宿主挂载后,再重试该节点;Barn 不会创建空目录代替。 restart、reload、recreate 会在停止已有节点前校验源目录。

名称与地址

节点名依次取 nodename、<pg_cluster>-<pg_seq>、node-<IP末段>,且必须唯一。 名称长度为 1–63,只能包含小写字母、数字和连字符,不能以 - 开头或结尾。 非空显式 nodename 优先,此时无需使用其他 pg_cluster、pg_seq 值派生名称。 vm_alias 是小写 DNS 风格名称列表,不能与节点名或部署内任何其他别名重复。

所有托管主机必须位于同一个 RFC1918 /24:.1 属于宿主,.2–.8 保留,节点使用 .9–.254。

Guest 内部,固定 IP 网卡就是承载 Inventory 地址的那块网卡(ip -br addr);其名称不是 Barn 契约。

漂移

Barn 对每个解析后节点计算哈希。新增主机由 up 创建;选中的已停止节点会启动, 运行中同伴保留进程,同时重试未完成的客机初始化。VM 定义变化需要节点级 recreate;删除主机条目只报告、绝不销毁。 deployment 架构、用户或子网变化需要整体重建。plan/up 会把镜像选择器解析为精确镜像身份, 因此 Catalog 更新后即使 Inventory 文本未改动,也应检查计划。修改用于派生节点名的字段会表现为旧节点 missing 加新节点,建议使用稳定、显式的 nodename。

2.2 - 命令行

Barn 命令、关键参数、结构化输出与退出码。

本参考描述 Barn 0.9.0 发布候选。编写脚本前先核对 barn version, 发布进度见当前状态。

barn [--json|--yaml] [-v|--verbose] <command> [flags] [node...]

已安装的二进制是当前版本最准确的参考。每一条可见命令都自带操作边界与可复制样例:

barn --help
barn setup --help
barn image pull --help

直接运行 barn 会显示简短欢迎信息和下一步命令,以 0 退出, JSON/YAML 输出 actions[]。barn image 这样的裸命名空间仍以 2 退出,文本模式打印帮助,JSON/YAML 模式返回结构化用法错误。显式 --help 始终输出 供人阅读的帮助文本并以 0 退出。用 barn --version 或 barn version 查看构建身份。

命令

范围 命令
准备 setup、init、validate、doctor
生命周期 plan、up、start、stop、restart、reload、recreate、status、destroy、purge
访问 ssh、exec、logs、provision、ssh-config、hosts install/uninstall
镜像 update、image list/info/pull/import/sync/prune/reset、repo scan/build/verify
宿主网络 network status/install/uninstall
macOS 客机(尚未发布) mac …,见 Mac 命令
其他 version、completion

没有命令会隐式刷新 Catalog。update 获取配置仓库的 Catalog,校验并激活; image sync 是为精确 URL 或文件准备的显式恢复路径。普通命令只使用当前本地 Catalog。 两者都不更新 Barn 可执行文件。

常用命令提供作用域明确的短别名:

命令 别名 命令 别名
setup s validate v
plan pl recreate rc
status st destroy de
ssh-config sc image images、im
doctor dt network n、net
exec / logs ex / l version ver

up、ssh、init、start、stop、restart、reload、provision、hosts、 completion 没有别名。请使用明确的 barn purge 拼写;rm 不是命令别名。 命名空间内部,hosts 与 network 的 install/uninstall 使用 i/u,network status 使用 st;image 使用 list=ls、info=in、pull=p、 prune=pr、sync=sy、import=i。

Barn 在选定的 BARN_HOME(默认 ~/.barn)中管理一套部署,其身份与 Inventory 所在目录无关。使用已应用状态的命令可在任意目录运行。配置来源由命令决定,-f 刻意不做全局参数:

命令 期望状态来源
setup [template] 显式 -f,否则发现配置,否则生成 meta;模板与 -f 互斥
init [template] 生成新 Inventory,不读取期望状态;--force 显式替换输出文件
validate 显式 -f,再发现配置;绝不回退到已应用状态
plan、up、reload、recreate 显式 -f,再发现配置,最后回退到已应用规格
其他生命周期/访问命令 不读取期望配置;使用已应用状态

没有配置文件且没有已应用部署时,交互式 up 可以生成默认配置;它也能准备缺少的宿主 依赖、恢复完整但未激活的 Barn 网络。该内部准备流程接受 setup 计划,sudo 仍可能 请求凭据;可先用 setup --dry-run 查看宿主计划。脚本应显式执行 setup --yes, 没有配置文件时无需另行 init。

关键参数

参数 含义
--json、--yaml stdout 机器可读;进度仍写 stderr;刻意不设短参数
-v、--verbose stderr 有界诊断
-c、--cidr 为 init/setup 生成模板或宿主网络检查/安装选择 RFC1918 /24
-f、--file 为读取期望状态的命令选择 Inventory
-r、--repo 在提供此参数的命令上选择仓库;覆盖 --mirror 与 BARN_REPO;validate 在 0.9 候选版本新增此参数
--mirror 为 setup、Catalog 与需要解析镜像的生命周期命令选择中国官方仓库
-m、--mode 在提供该参数的命令中选择 macOS host/shared 网络模式
-d、--dry-run 只展示 setup/image 计划,不改变状态
-y、--yes 应用已展示的宿主/setup/image 计划
--force(init、destroy、recreate) 覆盖生成文件或跳过输入确认词;因为 -f 用于选择 Inventory,所以只保留长参数
-n、--no-wait QEMU 运行后即返回,跳过 Guest 就绪检查、恢复与元数据刷新
--rollback(up、reload) 清除本次运行中 prepare 失败节点的残留产物
--delete-persistent 整体销毁时也删持久盘;不能与节点选择器一起使用
--purge 整体处置:删除磁盘、密钥与 deployment 状态,保留镜像

参数属于各自命令,下表列出容易混淆的作用域:

命令 专用参数
init --output/-o(默认 ./barn.yml,- 表示打印)、--cidr/-c、--force
plan --file/-f、--repo/-r;没有 --mirror 或 --dry-run
start、restart --no-wait/-n;没有 --file 或仓库选择参数
provision 必须提供 --script/-s;--sudo 使用客机 sudo -n;--parallel/-p 为 1–4,默认 1;--timeout/-t 为正值、最多 24h,默认 1h
ssh-config --install/-i 与 --remove 互斥;--name 默认为 barn;移除不接受节点,也不要求部署状态存在
logs --source/-s serial|qemu|events,默认 serial;--follow/-f;events 不接受节点
image info、image pull 可选镜像选择器、--arch/-a amd64|arm64、--repo/-r;只有 pull 接受 --mirror
image import --sha256/-s;指定 --name local-* 还必须提供 --boot/-b bios|uefi 与 --source-user/-u
image prune --dry-run/-d 与 --yes/-y 互斥;--repo/-r
image sync URL 或路径、--repo/-r、显式 --allow-downgrade
network install --cidr/-c 默认 10.10.10.0/24,--mode/-m 默认 host,--yes/-y;--archive/-a、--interface-id/-i 仅限 macOS
network status 可选 --cidr/-c;没有 --file
network uninstall、hosts install/uninstall --yes/-y

setup --dry-run 与 setup --yes 互斥。--cidr 用来调整生成模板的网段,不能重写显式 选择的 Inventory。validate --repo 是 0.9 候选版本新增参数,没有对应的 --mirror; 需要检查中国仓库时使用 --repo https://repo.pigsty.cc/barn。

0.9 候选版本中,network 与 hosts 的 install/uninstall 会在终端展示计划并询问确认 (安装默认同意,卸载默认拒绝);非终端只展示计划,除非传入 --yes。 macOS 首次网络安装使用 setup;候选版本 的 network install 会在 sudo 提示前引导到该命令。--yes 接受 Barn 计划,不能提供 sudo 密码。

--mirror、--force、--rollback、--remove、--allow-downgrade、--sudo、 --delete-persistent、--purge 等低频或扩大风险边界的参数只保留长版本。读取 Inventory 的命令中 -f 始终选择文件;logs -f 保留惯用的 --follow。 -n 始终表示 --no-wait,-d 始终表示 Dry-run。

存在部署时,barn purge 与 barn destroy --force --purge 执行相同的整体处置, 且无需确认。它不接受节点或 Inventory,删除整套 Deployment、 持久盘、密钥、状态和默认 SSH Fragment,保留镜像与宿主网络。没有部署时幂等成功, 也可清除能够证明归属的保留盘;缺少状态文件绝不会授权按路径删除无法证明身份的遗留节点工件。 0.9 候选版本中,没有部署时的普通整体 destroy 也返回成功;但 destroy --force --delete-persistent 和 destroy --force --purge 会报错,提示改用 purge。

结构化失败(0.9 候选版本)

下列统一失败契约描述 Barn 0.9.0 发布候选。

普通失败会在 stderr 输出 error: <消息>;外部工具失败时附上它 stderr 的最后几行; 有明确下一步时再输出一行 next:。SSH 子进程退出失败不会重复打印错误,直接保留子进程输出。 如果命令没有提供更丰富的类型化结果,结构化模式会输出通用失败对象,包含 error、message,以及适用时的稳定 reason、next、operation_id 和外部程序详情 command(name、argv、exit_status、signal、timed_out、stderr),然后返回退出码。 已携带失败状态的结果后面不会追加第二份 JSON/YAML 文档。 通用对象的 error 使用下方表格中的固定类别;recreate_required 和 nodes_removed 改为 error: "conflict" 下的 reason,旧的 resource_conflict 类别改为 resource。

非零退出不保证 stdout 一定是这个通用对象。 doctor、network、provision、 生命周期操作与远端命令可以返回各自的报告结构。SSH 子进程退出在内部归类为 remote_exit, 但公开结果包含 success、exit_code、stdout、stderr 等字段,可选 error 也不服从 通用错误分类契约。自动化应始终保留进程退出码,再按具体命令解释 payload。

生命周期结果

plan 是只读操作,即使 action 为 recreate 或 blocked-removal 也返回成功;自动化必须 检查 action 与 create、start、recreate、missing、blocked 字段。对于 Catalog 镜像,计划只读取本地配置和 Catalog,无需先安装 QEMU 或宿主网络;已注册的 local-* 镜像还会校验缓存,需要 qemu-img。计划不会下载镜像;它显示精确镜像、资源总量、变更原因 和磁盘影响。0.9 候选版本还逐项列出数据盘,包括隐式的 128 GiB /data。 宿主能力与地址可用性由 up 在执行前检查。up 会创建缺失节点、启动已停止 节点、复查运行中节点的就绪状态,并根据完整的 applied deployment 重写 Barn 安装的 SSH 客户端配置;recreate 同样执行全量刷新,节点级 destroy 删除旧条目,整体 destroy 移除该配置。start 启动已停止节点并复查运行中节点的就绪状态,start 与 restart 也会刷新 SSH 别名。 破坏性 drift 返回冲突,并给出下一步命令:先 barn plan,再 barn recreate <node> 或 barn destroy <node>;终端上这两条命令会要求输入确认词,--force 仅用于脚本。 如果 VM 生命周期成功但 SSH 客户端配置无法写入,命令会给出警告并返回成功; barn ssh 仍然可用。结构化输出通过 warnings[] 报告集成问题。 0.9 候选版本不修改符号链接或硬链接形式的 ~/.ssh/config,会发布独立配置片段, 并提示需手动加入的 Include 行。

就绪边界是管理 SSH 可用。可选初始化问题通过 nodes[].warnings 报告,已完成的恢复 操作(包括数据盘重置)写入 nodes[].repairs。客机可用但有这些限制时返回 0;重复 up 会重试未完成步骤,无需重启运行中的 VM。要求全部配置功能可用的自动化应检查警告字段。

生命周期批处理出现可隔离的节点级失败时,即使所有选中节点都失败也可能返回 5,并报告 N of M node(s) failed: <node> (<stage>: <error>); ...。常见阶段包括 prepare、start、 readiness、bootstrap、guest-setup、stop、status;readiness 或 bootstrap 失败会追加 run \barn logs ` for the guest console。结构化输出携带 failures[](node、stage、error,**0.9 候选版本**还有可选 reason);当 –rollback清除了 从未提交节点的 prepare 产物时,还会带上rolled_back`。参见 节点未就绪。

status 默认展示节点、状态、IP、精确镜像和 CPU/内存;--verbose 展示 SSH 端口、 架构、加速器与 PID。TCG 在普通文本中也有标记。一个节点异常时,仍保留其他节点的 状态,并返回 5;结构化输出包含逐节点 error 和 failures[]。running 表示 VM 正在运行,不代表本次 status 检查了 guest 就绪状态。

启动命令完成后还会刷新运行中 guest 的 Barn hosts 和控制节点 SSH 配置;停止中的 节点在下次启动时更新。--no-wait 会跳过 guest 就绪检查、恢复和刷新,随后执行 up 补齐。 局部 recreate 若仍受未选节点的配置变化影响,会在停机、删盘前拒绝;按提示一次选择 需要重建的节点。

控制节点中由 Barn 管理的 SSH 条目不固定 guest 主机密钥,也不写入 known_hosts, 因此重建实验节点后可以直接连接。用户自行添加的 SSH 配置会保留。

恢复行为

up、start 按节点隔离宿主共享目录 缺失的影响;up 在新节点准备失败后仍会启动独立的已有停止节点。部分成功保留退出码 5 和成功节点。重试提示保留配置文件、镜像仓库及适用参数,start 的重试仍为 start。

setup 与随后生命周期重试使用同一个 operation_id。首次 setup 失败、尚无部署状态时, 也可通过 barn logs --source events --json 读取有大小上限的阶段日志。setup 日志不记录 命令参数和认证信息,详细根因以命令输出为准;setup --dry-run 不写日志。 destroy --delete-persistent 与 purge 成功摘要只描述最终删除、保留的资源;purge 仍保留镜像缓存和宿主网络。 先删除某个节点后留下的受管持久盘,不再阻断其余节点的销毁。普通 destroy 继续保留 这些盘,只有显式删除持久盘或 purge 才会移除它们。

macOS 新网络安装先完成 Homebrew 发现/安装或固定归档下载,再申请管理员认证。 这避免了 Homebrew 清除先前 sudo 凭据导致的安装失败,不扩大特权操作范围; 下载失败时不会提前要求输入密码。

中断操作恢复(0.9 候选版本)

候选版本会把已被无关进程复用的 QEMU PID 识别为节点停止。stop 中断而 VM 仍运行时, 状态会恢复为 running;其他未完成过渡会指出用于完成它的命令。destroy 会自行处理 中断过渡。首次 up 失败后可以编辑 Inventory 再重试,因为未提交产物按照日志记录回滚。

日志与环境变量

logs 默认读取客机串口;--source qemu 读取 QEMU 诊断,--source events 读取有大小 上限的部署事件日志。使用 --follow 时,文本流式输出字节,JSON 输出 NDJSON 记录, YAML 输出文档流。0.9 候选版本将普通 events/qemu 日志读取显示为可读记录, 只有 --verbose 才显示 QEMU argv。

环境变量 用途
BARN_HOME 绝对路径的私有状态目录,默认 ~/.barn;不能是符号链接或用户主目录等范围过大的目录
BARN_REPO 默认仓库;被命令提供的 --mirror、--repo 依次覆盖
BARN_OUTPUT text、json、yaml;展示参数优先
BARN_VERBOSE 布尔诊断默认值;展示参数优先
BARN_VMNET_ARCHIVE macOS setup 使用的固定 socket_vmnet 归档绝对路径,仍执行摘要检查
NO_COLOR 非空时关闭颜色

SSH 透传与命令补全

barn ssh [node] [--] [command ...] 打开会话或运行可选命令; barn exec [node] [--] <command ...> 必须给出命令并透传退出码。-- 之前的展示参数 属于 Barn。ssh 中 -- 之后的参数会像普通 SSH 一样以空格连接,再交给远端 shell 解释; exec 保留多个参数的边界,需要 shell 展开或管道时请显式使用 sh -c; 单个命令字符串仍保留 shell 简写行为。 有 -- 时,其前面只能是空或一个已知节点。为方便交互使用,也接受省略 --:已知 首参数选节点,否则把整段当成默认节点上的命令,并显示 warning。0.9 候选版本会检查 包含数字或 - 的首参数是否像节点名误拼:长度不超过四个字符时最多一个编辑距离, 更长时最多两个。符合时会拒绝执行;ls、df、wc 等普通命令仍可运行。脚本中请明确写 --。

加载 barn completion bash|zsh|fish|powershell 可获得命令与作用域准确的参数补全, 同时补全命令别名、模板、镜像别名、枚举参数,以及从期望/已应用规格只读解析出的节点名。 0.9 候选版本还会让 -f 补全只列出 YAML 文件。

退出码

此表列出 Barn 0.9.0 发布候选的退出码契约。缺少配置、未知镜像均为 usage(2); setup/network 失败按原因区分为 runtime(1)或 capability(3)。

代码 error 含义
0 成功,包括客机可用但可选功能受限
1 runtime 操作已执行但失败(外部工具、下载或客机失败)
2 usage 命令行或 Inventory 有误
3 capability 宿主缺少工具、Barn 网络或权限
4 conflict Deployment 当前状态不允许,或另一个 barn 命令正持有它
5 partial 节点级批处理失败;检查 failures[],已经成功的同伴会保留
6 resource 宿主地址、端口、网段或磁盘被占用
7 integrity 已校验的摘要、签名、身份或属主不一致
130 cancelled 被中断(SIGINT/SIGTERM)或拒绝确认

0.9 候选版本中,修改类命令遇到另一个 Barn 命令持有部署锁时,最多等待 10 分钟 并指出对方;超时以 4 退出,reason 为 deployment_busy。status、ssh、exec、 ssh-config、hosts 不等待。status 在显示已记录状态时通过 note 报告并发操作; 这不代表该部署操作已完成。

ssh 与 exec 原样透传 SSH 子进程退出码,包括 255;255 可能是 SSH 连接失败, 也可能是远端命令返回该值。文本、JSON 与进程退出码保持一致。

2.3 - Mac 命令

barn mac 的命令与参数、机器规则、JSON 结果、失败原因、网络与文件。
重要

Barn 0.9.0 发布候选,尚未发布。 当前验证结果与发行前检查见 当前状态。请以实际运行的 barn mac --help 为准。

barn [--json|--yaml] [-v|--verbose] mac <command> [flags] [name...]

barn mac 需要 Apple 芯片与 macOS 27 或更高版本,以已登录用户身份运行,拒绝以 root 运行。在其他宿主上该命令默认隐藏,需要 Mac 组件的命令会以 mac_host_unsupported 失败。不带子命令的 barn mac 等同于 barn mac ls。

命令

命令 用途
ls 列出所有机器的状态、地址、SSH、macOS 版本、资源与共享;别名 list、status、st
up [name] 按需创建机器,启动并等待 SSH 与 sudo 可用
start [name...] 启动已有机器
stop [name...] 正常关机,两分钟后仍未停止则断电
restart [name] 先停后启,使配置变更生效
open [name] 显示桌面,机器已停止时先启动
ssh [name] 交互式终端;-- 之后是交给客机 shell 的命令行
exec [name] -- cmd 执行命令并保留参数边界
configure name 修改机器设置
recreate name 用全新的 macOS 替换机器,保留其设置
destroy name... 删除机器
password [name] 显示或复制登录密码
ssh-config 打印、安装或移除 OpenSSH 条目
logs [name] 最近的运行日志
setup 只准备 macOS 基础镜像,不创建机器
image ls 列出恢复镜像与基础镜像及使用它们的机器;别名 list
image update 把 Apple 最新的 macOS 27 准备为默认基础镜像
image prune 列出不再使用的镜像,加 --yes 才删除
doctor 检查宿主、组件、基础镜像与每台机器

各命令的参数

命令 参数
up --cpu --memory --disk --user --share --clipboard --subnet --ipsw -y/--yes -n/--no-wait --open
start --all -n/--no-wait --open --recovery
stop --all --force
restart -n/--no-wait --open
configure --cpu --memory --share --unshare --clipboard --subnet
recreate --update --force -n/--no-wait
destroy --force
password -c/--copy
ssh-config -i/--install --remove
logs -n/--lines(默认 100,最多 10000)
setup --ipsw --disk -y/--yes
image update --ipsw -y/--yes
image prune --installers -y/--yes

不带机器名称的命令作用于唯一的一台机器或 mac1;有多台机器且没有 mac1 时会要求 指定名称。start 与 stop 可接收多个名称或 --all。destroy 与 recreate 会先说明 将删除的内容,并要求输入命令名确认;没有终端时用 --force 确认。

参数取值

参数 取值
--cpu 虚拟 CPU 数,至少 2,不超过 Mac 的逻辑 CPU 数;默认 4
--memory 16G、16GiB、16GB 或字节数;至少 4 GiB,不超过物理内存;默认 8 GiB
--disk 基础镜像容量,至少 32 GiB;默认沿用已准备的基础镜像,即 100 GiB。其他容量会安装另一个基础镜像
--user 管理员账号;默认你的 macOS 用户名,该名称不合法时为 barn
--share [name=]path[:ro|:rw],可重复,最多 8 个;名称默认取路径最后一段;~/ 展开为主目录
--clipboard on 或 off;默认 on
--subnet 规范的私有 /24,例如 10.10.30.0/24;auto 表示第一个空闲网段

up 遇到与已有机器不同的创建参数时直接拒绝而不是忽略,并在 next: 行给出修改方法。 CPU、内存、共享、网段与剪贴板用 configure 修改。账号与磁盘容量在机器的整个生命周期内 固定,recreate 也会保留它们:需要其他取值时请另建机器。更换 macOS 版本需先执行 image update,再执行 recreate --update。

机器

  • 名称:1–32 个小写字母、数字或中间连字符,以字母开头,例如 mac1、dev、build-2。
  • 运行上限:每台 Mac 同时运行两台 macOS 虚拟机,其他工具与 macOS 安装过程也计算在内。 Barn 从不为腾出名额而停止任何机器。
  • 账号:管理员账号,免密 sudo、SSH 密钥登录、桌面自动登录,并开启远程登录; SSH 密码登录被关闭。登录密码随机生成,保存在机器目录的 password 文件中。
  • 客机名称:电脑名称即机器名;本地主机名为 barn-<name>,因此客机以 barn-<name>.local 应答。
  • 共享:一个由 macOS 挂载到 /Volumes/My Shared Files/<name> 的 VirtioFS 设备。 共享必须是已存在的目录,不能是符号链接,只能在机器停止时修改。
  • 剪贴板:纯文本,在窗口获得或失去焦点时经这台机器的 SSH 连接同步;最大 1 MiB; 标记为敏感的内容不会发送。
  • 停止:通过客机中的 macOS 正常关机;两分钟后仍在运行则断电,结果中带 "forced": true。--force 立即断电。

网络

每台机器的网络由它自己的 runner 进程在启动时创建,停止时随之消失,不涉及任何守护进程或 root 权限。

项目 取值
网段 在 10.10.20.0/24 到 10.10.59.0/24 之间选择第一个空闲的私有 /24,避开宿主路由和其他机器;也可用 --subnet 指定
网关 .1,即 Mac
客机地址 .10,通过对机器 MAC 地址的 DHCP 保留分配
可达性 经 NAT 访问 Mac 与互联网;不能访问其他机器与局域网

宿主路由(例如 VPN)与机器网段重叠时,start 会以 mac_subnet_in_use 拒绝启动。 SSH 主机密钥绑定到机器实例而不是地址,因此 configure --subnet 后信任关系不变。

macOS 的“本地网络”隐私控制会阻止未获授权的第三方程序连接这些网络,报错为 “No route to host”;需要在隐私与安全性 → 本地网络中允许对应应用。Barn 自身通过 Apple 的 /usr/bin/nc 与 /usr/bin/ssh 连接,不受该限制。

JSON 输出

所有命令都支持 --json 与 --yaml,进度信息输出到标准错误。

ls

{
  "schema_version": 2,
  "root": "/Users/alice/.barn/mac",
  "prepared": true,
  "base": {"version": "27.0", "build": "26A428", "base_id": "26A428-e16af589f4b705ca397f5b21"},
  "machines": [
    {
      "name": "mac1",
      "kind": "macos",
      "state": "running",
      "ready": true,
      "ssh": "ready",
      "address": "10.10.20.10",
      "address_stable": true,
      "ssh_host": "10.10.20.10",
      "ssh_port": 22,
      "user": "alice",
      "image": {"version": "27.0", "build": "26A428", "base_id": "26A428-e16af589f4b705ca397f5b21"},
      "cpus": 4,
      "memory_bytes": 8589934592,
      "disk": {"capacity_bytes": 107374182400, "allocated_bytes": 1202647040},
      "network": {"subnet": "10.10.20.0/24", "gateway": "10.10.20.1", "address": "10.10.20.10"},
      "shares": [{"name": "src", "host": "/Users/alice/src", "guest": "/Volumes/My Shared Files/src", "readonly": false}],
      "clipboard": true,
      "pid": 2545,
      "instance_id": "b1482ffc-2da7-45d9-ace5-c5f3193a9172",
      "warnings": []
    }
  ],
  "running": 1,
  "limit": 2
}
字段 取值
state prepared(尚未完成首次启动)、starting、running、stopping、stopped、unknown
ready 仅当本次检查通过 SSH 登录客机并验证 sudo 时为 true
ssh ready、pending(首次启动进行中)、unavailable、offline、unchecked
observed 客机报告的 macOS 版本与基础镜像不同时出现
window_visible 桌面窗口显示期间出现
error、warnings 最近一次记录的失败,以及本次检查发现的 SSH 问题

生命周期结果

up、restart、open、recreate 与 configure 返回单个结果;start、stop 与 destroy 返回 {"machines": [...]},每台机器一项,只指定一台时也是如此。

{"name": "mac1", "action": "created", "state": "running", "ready": true,
 "address": "10.10.20.10", "user": "alice", "version": "27.0", "build": "26A428"}
字段 取值
action created、started、running(已在运行)、restarted、recreated、opened、configured、stopped、powered_off、already_stopped、destroyed、absent
forced 正常关机未完成、只能断电时为 true
window 显示了桌面时为 true
warnings 不影响结果的后续事项,例如下次启动才生效的变更

exec --json 返回与 Linux barn exec --json 相同的对象:node 为机器名, exit_code、stdout 与 stderr 来自客机。交互式 ssh 没有 JSON 形式。

失败

退出码与 Barn 命令行一致;远程命令自身的退出码经 ssh 与 exec 原样返回。JSON 失败结果带有稳定的 reason 与 next 命令:

Reason 退出码 含义与下一步
mac_host_unsupported 3 不是 Apple 芯片,或 macOS 低于 27
mac_runner_missing 3 命令行旁边没有安装 Mac 组件
mac_runner_protocol 3 命令行与组件来自不同构建,请一起安装
mac_root 2 请以普通登录用户运行,不要使用 sudo
mac_download_consent 2 没有终端时下载 macOS 需要 --yes,或改用 --ipsw
mac_machine_absent 4 没有该名称的机器;执行 barn mac up NAME
mac_not_initialized 4 机器尚未完成首次启动;执行 barn mac up NAME
mac_not_running 4 ssh/exec 需要机器正在运行;执行 barn mac start NAME
mac_running 4 该变更需要先停机;执行 barn mac stop NAME
mac_configuration_conflict 4 up 的参数与已有机器不同;按提示执行 configure 或其他命令
ssh_config_linked 4 ~/.ssh/config 是链接;请手动加入打印出的 Include 行
mac_vm_limit 6 已有两台 macOS 虚拟机在运行;停止提示中的那台
mac_subnet_in_use 6 宿主路由与机器网段重叠;执行 configure NAME --subnet auto
disk_full 6 可用空间不足以下载或安装 macOS
mac_machine_damaged 7 启动过的机器丢失了磁盘或身份文件;其目录原样保留
mac_readiness_interrupted 130 stop 中断了首次启动时的 SSH 等待

文件

$BARN_HOME/mac/
  config.json                        安装标识与默认基础镜像
  images/ipsw/<build>.ipsw(.json)    Apple 恢复镜像;下载中为 .partial
  images/base/<id>/                  只读、从未启动过的 macOS 基础镜像
  slots/<name>/state.json            机器记录(schema 2)
  slots/<name>/disk.asif             基础镜像之上的写时复制磁盘层
  slots/<name>/machine-id.bin        Apple 机器标识
  slots/<name>/auxiliary-storage.bin 启动存储
  slots/<name>/id_ed25519(.pub)      机器的 SSH 密钥对
  slots/<name>/known_hosts           固定的主机密钥,别名为 barn-mac-<instance>
  slots/<name>/password              登录密码,权限 0600
  slots/<name>/runner.log            运行日志(barn mac logs)

运行时 socket 位于 /tmp/barn-mac-<uid>-<hash>/。ssh-config 写入 ~/.ssh/barn-mac_config,并在 ~/.ssh/config 中加入一个 # barn-mac:include 区块,与 Linux 的 # barn:include 区块互不影响。桌面窗口位置保存在 ~/Library/Preferences/io.pgsty.barn.mac-runner.plist。

Barn 在客机中写入 ~/.ssh/authorized_keys、/private/etc/sudoers.d/80-barn、 /etc/ssh/sshd_config.d/000-barn.conf,设置电脑名称与本地主机名,并用 pmset 关闭睡眠。

2.4 - 镜像

签名 Catalog、内置别名、仓库选择、本地缓存校验、导入与清理。

Barn 使用物化的静态 Catalog 与不可变 qcow2 工件。官方与 HTTP Catalog 必须签名; 用户显式选择的本地或 HTTPS 仓库可以不签名。更新 Catalog 不需要发布新的 Barn 二进制,但二进制决定信任哪些签名公钥与镜像安全规则。

警告

EL7、EL9 9.3/9.6 与 EL10 10.0 是 deprecated 兼容镜像;其余内置版本均为 supported。

别名与拉取顺序

Barn 0.9.0 内置 Catalog 2026092902,包含 9 个 Family、39 个工件。el7 只有 amd64,其余 Family 均有 amd64 与 arm64。 EL9 包含 9.3、9.6、9.7、9.8;EL10 包含 10.0、10.1、10.2。 默认请求为本机架构的 u24:stable(Ubuntu 24.04)。

以下 stable 均覆盖 amd64 和 arm64。这是内置 Catalog 快照,不是实时仓库列表。 运行 barn update,再用 barn image list 查看选定仓库当前的目录。带日期的公开 端点检查与 Guest 小版本观测见当前状态。

Family 内置 stable 发行版系列
d12 20260923.2610.1 Debian 12
d13 20260914.2601.2 Debian 13
el8 8.10.20240528.2 Rocky Linux 8.10
el9 9.8.20260525.2 Rocky Linux 9.8
u22 20260926.0.0 Ubuntu 22.04 LTS
u24 20260926.0.0 Ubuntu 24.04 LTS
u26 20260927.0.0 Ubuntu 26.04 LTS

Debian 保留离线安装的 XFS 工具和已生成的 en_US.UTF-8,默认 locale 仍为 C.UTF-8。Ubuntu 保留 Canonical 原始镜像,账户与网络由启动时的 cloud-init 配置。 Debian 12 的 9 月 23 日上游构建仍缺少 XFS 工具和 en_US.UTF-8,这两项定制仍然 必要。上述 Ubuntu 原版已包含二者,amd64、arm64 均于 9 月 29 日通过 locale 和 XFS 数据盘检查。 更新 Catalog 只改变新解析的 stable;既有 VM 和显式锁定版本继续引用原来的基础镜像。

别名 发行版 架构 启动 状态
el7 CentOS Linux 7.9 / 2211 amd64 BIOS deprecated
el8 Rocky Linux 8.10 amd64、arm64 UEFI supported
el9 Rocky Linux 9.7 / 9.8 amd64、arm64 UEFI supported
el9 Rocky Linux 9.3 / 9.6 amd64、arm64 UEFI deprecated
el10 Rocky Linux 10.1 / 10.2 amd64、arm64 UEFI supported
el10 Rocky Linux 10.0 amd64、arm64 UEFI deprecated
d12、d13 Debian amd64、arm64 UEFI supported
u22、u24、u26 Ubuntu amd64、arm64 UEFI supported
barn image list
barn image info d13
barn image info d13:stable
barn image info el9@9.7
barn image pull d13@20260914.2601.2
barn image pull d13 --arch arm64
barn update

Catalog 状态只表达支持策略,不是启动开关:supported 表示已通过声明的支持门禁; testing 可在显式测试/风险接受下使用,但不受支持;deprecated 只为 EOL 兼容保留; unknown 尚无支持分类。非 supported 条目仍可运行,但会打印警告。

拉取时 Barn 会:

  1. 为整条命令读取一次选定仓库的本地 Catalog:即本次构建内置的 Catalog,或最近一次 为该仓库通过 barn update/image sync 激活的 Catalog;
  2. 解析 image[:channel] 或 image@version-prefix,官方 Catalog 缺省为 u24:stable; 独立 image pull 默认使用本机架构,可通过 --arch 覆盖;生命周期解析遵循 vm_arch;
  3. 只有尺寸、SHA-256、qcow2 结构全部匹配时才复用本地文件;
  4. 否则下载 Catalog 指定的准确工件,并支持重试和断点续传;两个官方仓库可互相回退, 自定义仓库仍为唯一来源。接受的字节始终须匹配 Catalog;不可变 Upstream URL 只用于溯源。

Release 构建默认使用 https://repo.pigsty.io/barn;仅有长参数的 --mirror 选择 https://repo.pigsty.cc/barn。优先级依次为 --repo、--mirror、BARN_REPO、 全球默认仓库,两个官方根都保持规范的签名 Catalog 信任。仓库选择同时决定本地 Catalog 槽位和下载来源;即使字节已缓存,仍需选择相同的自定义仓库。Barn 不会自动刷新 Catalog,已有激活目录与已校验缓存时,普通镜像解析可以离线进行。 运行 barn update 可获取、校验并激活选定 仓库当前的 Catalog。Catalog 更新使用该指定源,失败时直接报错;镜像下载则在所有 允许的来源均无法提供通过校验的字节时失败。 仅改变 --repo 不会获取或激活该仓库的 Catalog;使用它的自定义别名前,先运行 barn update --repo <root>。

已校验但可写的缓存文件会恢复为只读;损坏且未被引用的缓存会先保留为带 .corrupt-<timestamp> 后缀的文件,再重新下载。仍被 VM 引用的基础镜像保持原位并报错。

运行时策略

匹配架构正常使用原生 HVF/KVM,只有一个 Catalog 已知例外:Stock EL8 arm64 的 64K Granule Kernel 无法通过 Apple HVF 运行,因此 Apple Silicon 会自动选择可见的同架构 TCG。显式外来 vm_arch 也会使用 TCG;arm64 宿主上的 amd64 Guest 使用单翻译线程, 以保留 x86 内存序。TCG 结果不能作为性能证据。

EL7 刻意仅支持 Linux/amd64 原生运行。Linux setup 只安装宿主原生 QEMU;外来架构必须 先安装对应 System Emulator 与 UEFI 固件,up、recreate 才会继续;plan 无需 这些工具就能解析 Catalog 镜像与运行时;但 local-* 命名导入在解析时会检查缓存字节, 仍然需要 qemu-img。

barn image pull d13 --mirror
barn image pull d13 --repo https://mirror.example/barn
BARN_REPO=/absolute/local/repository barn up

未签名仓库必须是本地路径或 HTTPS。HTTP 仓库必须提供可信密钥签名;不可变 Upstream 工件 URL 必须使用 HTTPS。

信任与校验

当前普通构建已经内置两把生产校验公钥;私有签名密钥不在源码仓库中。Catalog 激活会拒绝 未知密钥、畸形内容、同 Revision 异内容,以及低于该仓库独立 High-water Mark 的 Revision;只有操作者显式允许时才可降级。

镜像必须是尺寸与 SHA-256 匹配的纯 qcow2,不得有 backing file、外部数据文件、加密或 未知不兼容 Feature。通过校验的 Base Image 变成只读;节点根盘使用 Overlay,永不修改 Base。

barn update
barn image sync --repo https://repo.example/barn \
  https://repo.example/barn/catalog.json
barn image sync --repo /absolute/repo --allow-downgrade /absolute/repo/catalog.json
barn image reset

image reset 恢复二进制内置的 Catalog,但不会清除防回滚 High-water Mark。

barn update 立即检查仓库并激活更新的 Catalog。Barn 不会自动刷新 Catalog;每个版本 内嵌的 Catalog 会一直使用到你运行 update。image sync 是指定精确 URL 或文件(含降级)的 恢复路径。

按仓库恢复时要显式传入同一个根目录:

barn image sync --repo /srv/barn --allow-downgrade /srv/barn/catalog.json
barn image reset --repo /srv/barn

--repo 决定独立的活动 Catalog 与 High-water 槽,位置参数中的源不会改变这个选择。 image sync、image reset 接受 --repo,不接受 --mirror;省略 --repo 时使用 BARN_REPO 或编译期默认值。未签名自定义 Catalog 的精确源必须是选定根下的 catalog.json。

静态仓库格式

发布根刻意保持很小:

barn/
├── repo.yaml
├── catalog.json
├── catalog.json.minisig       # 官方与 HTTP 仓库必需
└── images/
    └── <image>-<version>-<arch>.qcow2

repo.yaml 保存人工意图:默认值、别名、Channel、精确版本、架构、启动模式、状态和可选、 只用于溯源的 Upstream URL。source_user 记录镜像声明的源登录身份,例如上游镜像的 rocky,或经过 Barn 官方归一化后的 dba。流水线清理候选镜像时另行接收上游账号。 Catalog/导入元数据不会替换 deployment SSH 用户(默认 dba),也不会自行归一化镜像。 该文件不保存任何生成的摘要或大小;catalog.json 保持同一逻辑树, 但为每个 Variant 物化文件名、SHA-256、工件大小和虚拟大小。repo.yaml 是 schema: 1; 生成的 catalog.json 则是 Barn 内嵌并签名的 Schema-3 Catalog。

schema: 1
revision: 1
defaults: { image: u24, channel: stable, arch: native, boot: uefi }
images:
  u24:
    aliases: [ubuntu24, noble, ubuntu]
    channels: { stable: "1" }
    versions:
      "1":
        status: unknown
        variants:
          amd64: {}
          arm64: {}

不显式设置 file 时,两个预期工件分别是 images/u24-1-amd64.qcow2 与 images/u24-1-arm64.qcow2;已有自定义文件可在 Variant 中覆盖为安全 basename。

Channel 与数值前缀都是可移动 Selector。存在精确 Key 时优先精确匹配;否则只在点分量 边界匹配并选择数值语义最新版本(el9@9.7 选择最新 9.7 Build,el9@9 选择最新 9.x Release)。不可变工件身份仍是 (image, exact version, arch):

d13:stable + native
  -> d13@20260914.2601.2 + arm64
  -> images/d13-20260914.2601.2-arm64.qcow2

barn repo scan 只读;build 执行严格 YAML 校验、完整 qcow2 inspect/check, 并原子替换 Catalog,永不修改 repo.yaml 或 QCOW 字节;verify 要求新鲜物化结果与 现有 Catalog 逐字节一致。build、verify 需要本机 qemu-img,scan 不需要。 应在安装 QEMU 的机器上构建,先发布不可变工件,最后发布 Catalog 与匹配签名,尽量 一起切换两者;正文与签名不一致时验签会失败。 修改 Catalog 内容时必须增加 revision。

本地布局与导入

镜像位于 BARN_HOME/images(默认 ~/.barn/images):各 Family 目录保存下载工件, manifests/ 保存当前激活的 Catalog 与每个仓库独立的 High-water 状态,local/ 与 local-images.json 保存导入镜像。

barn image import --sha256 <digest> /path/to/base.qcow2
barn image import --name local-mybase --boot uefi \
  --source-user ubuntu --sha256 <digest> /path/to/base.qcow2

CLI 中 --sha256 是可选参数;提供独立获得的可信摘要,才能在必做的 qcow2 检查之外加入 显式真实性校验。导入只复制和校验文件,不会清理凭据、安装 cloud-init、识别 Guest CPU 架构或证明镜像可启动。

命名本地别名必须以 local- 开头,避免未来签名 Catalog 遮蔽它们。--name、--boot、 --source-user 必须同时提供。命名导入记录执行导入的宿主原生架构,没有 image import --arch 参数;外来架构镜像应使用声明明确 Variant 的静态仓库。 别名不可变,镜像字节或元数据改变时应使用新名字。在 Inventory 中通过 vm_image: local-mybase 选择命名导入;不指定名字的导入只填充缓存。

清理

barn image prune --dry-run
barn image prune --yes

不带参数的 prune 与 --dry-run 只报告候选,--yes 才执行删除。保护集合是选定活动 Catalog 中的全部工件、已应用节点的镜像摘要,以及注册的本地别名。因此,即使没有 VM 使用,当前 Catalog 镜像和命名导入仍会保留。未被保护的镜像与识别出的过期 Staging File 才是候选;不安全或损坏的文件会导致报错。检查自定义 Catalog 的缓存策略时,要传入 相同 --repo。执行 destroy、destroy --purge 与 purge 后镜像仍会保留。

使用 go run ./tools/catalogexport /absolute/new/catalog.json 可逐字节导出编译期 Schema-3 Catalog。 公开 Catalog 若使用相同版本,就必须使用完全相同的字节;同版本不同内容会按 equivocation 拒绝。Release 签名与镜像 Catalog 签名仍属于不同信任域。

2.5 - 镜像流水线

不下载、不上传、不签名地校验或离线归一化显式 qcow2 Candidate。

底层 packaging/image-pipeline/build.sh 接受一份已下载的不可变 qcow2 与独立获得的 SHA-256。它绝不下载、上传、修改 Barn 运行时/网络状态、读取签名密钥,也不会把镜像 标成 supported。

以下命令从 Barn 源码目录执行。需要 Python 3 与 qemu-img;offline 还需要可用的 libguestfs virt-customize、virt-cat。这是镜像构建宿主的依赖,与 barn setup 为运行 VM 安装的依赖是不同边界。

模式

  • validate:复制并重哈希,强制 qcow2 检查,校验单元素 Backing Chain,运行 qemu-img check,输出明确不可发布的证据 Bundle;不会修改 Guest 凭据。
  • offline:额外在 Staged Copy 上使用 libguestfs virt-customize --no-network 与 virt-cat。它拒绝无关 UID/GID 88 占用,归一化锁定的 dba/admin 身份,关闭密码与 Root SSH,清理密钥/历史/Host Identity/cloud-init Cache,恢复定向 SELinux Label, 并回读确定性 Marker。

官方 Candidate 矩阵

build-official.py 在同一离线边界上封装固定的八目标矩阵:Debian 12/13 与 Rocky Linux 8/9,各自覆盖 amd64、arm64。每份上游 qcow2、RPM/DEB 输入、Release 名称、Digest 与 Source Epoch 都锁定在 official-v1.json。

./packaging/image-pipeline/build-official.py --list

./packaging/image-pipeline/build-official.py \
  --source-cache /absolute/source-cache \
  --package-cache /absolute/package-cache \
  --output /absolute/existing-output-root \
  --target d13/arm64 --fetch

不加 --fetch 时,全部锁定输入必须已经位于两个 Canonical Cache 目录;加上后,Wrapper 也只下载固定 HTTPS URL,并在调用离线归一化前拒绝任何 Digest 不匹配。Debian 12/13 安装锁定的 XFS 用户态闭包;Rocky Linux 8 安装锁定的 python36 与 python3-pip RPM,并在 cloud-init 启用 NTP 时使用镜像已有的 RHEL chrony 模板与 chronyd 服务; Rocky Linux 9 不需要额外软件包输入。SELinux 标签恢复属于归一化步骤,不是另一组软件包输入。

Debian 同时生成 en_US.UTF-8,并保留 C.UTF-8 作为默认 locale;归一化脚本和 宿主端 Marker 校验都会检查这两项。镜像更新也会保留这两项客机要求。Ubuntu 使用固定 日期的官方原始镜像,不经过这套离线定制流程。

每份结果仍是未签名的 testing Candidate。不传 --target 时构建全部八个目标,重复 该参数可以选择多个目标。--list 显示当前源码锁定的精确版本;目前包含 Debian 20260923.2610.1/20260914.2601.2 与 Rocky Linux 8.10.20240528.2/9.8.20260525.2。

组装接收的是包含按名称命名的 Bundle 的父目录,不是各 Bundle 自身目录。若八个 构建都放在同一个输出根下,执行:

./packaging/image-pipeline/build-official.py \
  --assemble-from /absolute/existing-output-root \
  --output /absolute/new-candidate-repository

构建分散在不同根时,可以重复 --assemble-from。八个目标都必须有且只有一个 Bundle; 组装会创建新的静态仓库,并调用 PATH 中的 barn 执行 repo build 与 verify, 也可用 --barn /absolute/path/to/barn 指定程序。构建模式使用已存在的输出根, 组装模式的目标目录则必须不存在。生成仓库使用 candidate Channel,而不是 stable, 例如应选 d13:candidate。此过程不包含真机 Smoke、签名、上传或 Catalog 发布。

校验一个已下载镜像

SOURCE_DATE_EPOCH=1787486400

./packaging/image-pipeline/build.sh \
  --mode validate \
  --source /absolute/source.qcow2 \
  --expected-sha256 <digest> \
  --output /absolute/new/evidence-directory \
  --name u24 --release 20260801.0.0 --arch amd64 \
  --source-user ubuntu --boot uefi \
  --source-uri https://immutable.example/source.qcow2 \
  --artifact-url 'https://images.example/u24/{sha256}.qcow2' \
  --license NOASSERTION \
  --source-date-epoch "$SOURCE_DATE_EPOCH" \
  --manifest-version 2026082903

Source/Output 必须是绝对路径;Source 必须 Canonical、普通、非符号链接、复制期间稳定, 且不超过 16 GiB;Output 必须不存在。Builder 使用相邻排它锁、0700 Staging 与一次最终 Rename;失败只删除受保护的 Staging。

成功 Bundle 包含只读 qcow2、Recipe、SLSA Provenance、SPDX Boundary SBOM、状态为 testing 的 manifest-candidate.json、Validation Evidence 与 Checksums。候选 Manifest 是流水线证据格式;仓库组装才会生成运行时使用的 Schema-3 catalog.json。SPDX 文件 描述声明的输入/构建边界,并不是 Guest 文件系统的完整软件包清单。签名刻意位于流水线 之外。固定输入/工具下 validate 模式逐字节可复现;offline Mutation 必须构建两次并比较, 才能成为 Release Evidence。

发布仍需要对每条声明的宿主/Guest 路径进行运行时 Smoke,明确审查支持状态与溯源, 增加 Catalog Revision,进行生产签名,并校验公开工件。构建成功不能直接把 Candidate 改成 supported,也不能证明它已经公开可用。

3 - 关于 Barn

产品模型、实现边界、真机证据、当前限制与发布门禁。
  • 设计:为什么 Barn 只有一份 Inventory、一套 deployment 与一个固定 IP 网络。
  • 当前状态:严格区分已实现、真机验证与剩余发布门禁。
  • 工程与发布:源码、生成输出、软件包、镜像流水线与证据边界。

3.1 - 设计

Barn 的单 deployment 架构、网络、状态与安全边界。

一个有用的抽象

Barn 把一份 Pigsty Inventory 启动成一套本地 QEMU deployment。它刻意不再拥有 project marker、项目注册表、租约模型、Provider Layer 或第二种配置格式。

状态位于当前 Unix 用户的 BARN_HOME(默认 ~/.barn)。产品假设每台电脑只有一套运行中的 Pigsty; 这并不是 root 强制的跨用户单例。

节点级收敛

Barn 只提取已记录的 VM 与 Pigsty 原生字段,计算逐节点哈希,并保存应用状态与完整 进程身份。新增节点增量创建;up 也会启动选中的已停止节点,保留运行中同伴的进程, 同时重试未完成的初始化、刷新托管 hosts 与 SSH 配置。无法识别或确认损坏的测试数据 文件系统可能被清空重建,包括持久盘,详见数据盘。 定义变更需要显式节点重建;配置缺席永远不授权删除。

运行时选择

Guest 架构是部署级期望状态。省略或 native 跟随宿主;显式 amd64/arm64 会准确 选择对应 Catalog 工件。HVF/KVM 原生加速仍是默认路径;外来架构或 Catalog 已知的 镜像/宿主不兼容规则才会选择固定 TCG Profile。没有用户可传的 Accelerator 参数,也不会 因任意原生失败静默回退。

实际架构与加速器保存在每个 QEMU Invocation 中,并通过 status 展示。执行破坏性 recreate 前,Barn 会证明所选 QEMU 二进制与版本、网络后端、镜像字节、启动模式与固件。 以后若新二进制改变运行时策略,也不能把新旧节点混跑:Runtime Drift 必须整体重建。

双网卡与一个固定子网

管理网卡负责 DHCP、DNS、出网与回环 SSH;固定 IP 网卡负责宿主、节点间与 Ansible 流量。macOS 使用 socket_vmnet;Linux 优先跟随当前 NetworkManager,否则使用 systemd-networkd,并通过发行版 bridge helper 接入。若 networkd 尚未启动,只有在 Activation-safety 扫描证明现有 Unit 不会接管真实宿主链路后才启动。

Debian helper 会临时、可逆地限制给调用者真实加入的组。setup 必须通过一次非特权 QEMU bridge smoke;失败后自动回滚安装。

存储与配置有不同生命周期

Inventory 保存期望的 VM 定义;应用状态记录已经创建的内容,包括精确基础镜像身份与 运行时 Invocation。Catalog Channel 移动不会改写已有根盘。

通过校验的基础镜像只读共享,每台 VM 写入自己的根盘 Overlay。数据盘遵循独立的保留 契约:普通 Destroy 保留持久盘,显式磁盘删除或 Purge 才清除它们。镜像缓存清理又有 独立边界,还会保护活动 Catalog 与已注册本地别名。详见存储与访问 和镜像参考。

安全边界

QEMU 与所有 Guest 工件都以调用者身份运行。root 仅用于宿主软件包安装、网络与可选 hosts publisher。 销毁必须同时匹配属主、路径包含、节点身份、QMP/进程身份与工件白名单;任何歧义都会停止。

3.2 - 当前状态

Barn 0.9.0 发布候选、当前验证结果与发行前检查。

Barn 0.9.0 是尚未发布的候选版本。源码检查、本地构建、软件包、CI、发行和线上文档 分别核验。安装方式见快速上手。

文档基线

对象 当前身份 使用方式
程序与当前文档 Barn 0.9.0 发布候选 安装 Homebrew HEAD 或从源码构建;发行包尚未发布。
CLI 与配置 barn、barn.yml、BARN_* 使用版本相关说明前先检查 barn version。
状态与宿主资源 ~/.barn、Barn 网络与 helper 每个用户一套 Linux 部署;macOS 客机使用独立状态。
镜像仓库 官方入口的 /barn 前缀 已于 2026-09-29 发布签名 Catalog 2026092902 并完成公网核验,见下方镜像记录。

最终发布提交、制品摘要与安装渠道将在完成发布和下载核验后记录。

macOS 客机

barn mac 在 Apple 芯片上运行 macOS 27 虚拟机,见教程与 命令参考。组件名称为 Barn Mac.app,签名标识为 io.pgsty.barn.mac-runner,状态独立保存在 $BARN_HOME/mac。

2026-09-29,本地 CLI/hosts-helper 测试、原生 Bridge/镜像/退出提示/菜单测试、runner 编译、 ad-hoc 签名验证与 probe 通过。这些检查没有启动 VM,不代表完整 Mac 实机生命周期验收。

发行前仍需核验

  • 最终 Barn 提交的完整源码、归档、DEB/RPM、安装器与跨平台检查;
  • 全新宿主准备、Linux/macOS VM 生命周期与清理;
  • Mac Developer ID 签名与公证;
  • Barn 0.9.0 的发布与下载核验,包括 Homebrew。

Linux 镜像 Catalog:2026-09-29

两个官方 /barn 入口均已发布签名 Catalog 2026092902:9 个系列、39 个工件。 经过规范化的 Debian 与 Rocky Linux 镜像,其内部配置与元数据统一使用 Barn。

系列 稳定版本 架构
Debian 12 20260923.2610.1 amd64、arm64
Debian 13 20260914.2601.2 amd64、arm64
Rocky Linux 8 8.10.20240528.2 amd64、arm64
Rocky Linux 9 9.8.20260525.2 amd64、arm64
Ubuntu 22.04 / 24.04 20260926.0.0 amd64、arm64
Ubuntu 26.04 20260927.0.0 amd64、arm64

6 个 Debian 13、Rocky Linux 镜像通过 UEFI 启动、SSH、双网卡、UID/GID 88、Python、 cloud-init 与 XFS 数据盘检查。amd64 使用 KVM,Debian 13 和 Rocky Linux 9 arm64 使用 HVF;Rocky Linux 8 arm64 因上游 64 KiB 内核不兼容 Apple HVF,使用 TCG。 Rocky Linux 8 使用自带的 RHEL chrony 模板和 chronyd 服务。

Debian 12 与 Ubuntu 镜像通过原生 KVM/HVF 启动、SSH、双网卡、UID/GID 88、locale 和 XFS 数据盘检查。Debian 镜像包含锁定版本的 XFS 工具与 en_US.UTF-8,默认 locale 保持 C.UTF-8;Ubuntu 保留 Canonical 原始字节。镜像检查采用隔离的 QEMU user 网络, 完整宿主网络及 VM 生命周期仍需独立验收。

内嵌与公开 Catalog 字节一致,两个官方入口均通过签名校验,新镜像通过公网下载检查。 版本选择与更新行为见镜像参考。

3.3 - 工程与发布

源码边界、构建测试门禁、镜像归一化、发布输出与证据纪律。

本页描述 Barn 0.9.0 发布候选。构建命令使用当前工作区,请同时记录提交与 未提交变更。源码构建和本地检查通过不代表已经正式发布。

仓库边界

Barn 源码仓库包含代码、测试、构建/打包定义、法律声明、README.md、CHANGELOG.md、 CONTRIBUTING.md、SECURITY.md 与双语应用发布说明。本网站提供用户、设计、运维 与发布文档。运行行为和命令参数需要以匹配的源码及二进制核对;未发布源码的行为不能 代表公开软件包。

Review 记录、临时 Inventory、生成二进制与 Release 输出树不是生产源码输入。

以下输出随时可重建:

  • bin/:开发构建;
  • dist/ 与 .goreleaser-*:Release/Snapshot Staging;
  • 根目录 barn、barn-hosts-helper、catalogsign 二进制;
  • Hugo 的 public/ 与 resources/。

构建与源码门禁

make check

make check 包含模块与 Shell 检查、维护脚本归属、单元/Race 测试、Vet、Staticcheck、 死代码与 errcheck 检查、漏洞扫描、四目标跨平台构建、安装器/镜像流水线测试及许可证 检查,准确清单以 Makefile 为准。CI 还单独检查固定工具链、Go 格式、空白与 GoReleaser 配置。质量工具安装步骤见从源码构建。

打包逻辑变更还需要独立 Snapshot 门禁:

make release-check
make release-snapshot SNAPSHOT_DIST=.goreleaser-review

安装 packaging/toolchain.env 指定的 GoReleaser、nFPM、Syft 等版本;Snapshot 还需要 验证脚本使用的归档与系统软件包检查工具。输出必须是工作区根目录下尚不存在的新目录, 已有目录会被拒绝。Snapshot 仅在本地生成,不上传 Release。

源码检查不等于真机验证。macOS HVF、Linux KVM/网络、软件包消费、Release 发布与 线上网站渲染需要分别验证。make image-pipeline-native-test 是独立真机镜像流水线 门禁,需要 QEMU/libguestfs 与显式镜像输入。必填的 BARN_IMAGE_PIPELINE_NATIVE_* 变量见 tests/image-pipeline-native-test.sh, 该测试不会下载镜像。

Release 与软件包契约

packaging/、.goreleaser.yaml 与 .github/workflows 属于源码;它们生成的目录不是。 Archive 与 Linux Package 携带配套 CLI 和 hosts-helper 二进制、LICENSE、源码 README,以及根据 go.mod 锁定模块版本重建的准确上游许可证字节。Archive 的二进制 位于 bin/、许可证位于 licenses/;Linux Package 安装 /usr/bin/barn、 /opt/barn/libexec/barn-hosts-helper,文档位于 /usr/share/doc/barn/。

Linux Package 包含 BUILD_INFO.json。GoReleaser Archive 的构建身份在二进制中,发布元数据随资产单独提供,不能假定每种 Archive 都包含 该文件。依赖许可证在构建时生成暂存,详细用户文档保留在本网站。

应用 Release 由 GitHub Actions 构建,提供 checksums.txt、发布元数据与 SPDX SBOM 资产。当前工作流不生成单独的应用发布签名或 provenance/attestation 包。用于认证镜像 Catalog 的 Minisign 签名属于另一套信任机制。

Commit、Tag、归档/软件包验证、CI、草稿上传、公开发行与匿名下载验证应分别记录。 Tag 工作流创建草稿,不会直接发布。pre-1.0 版本在 GitHub 标记为预发布,安装器需要 显式指定 BARN_VERSION。

make release-local VERSION=<version> 在本地构建并验证,不执行发布。它要求干净 工作区正好位于对应 v<version> Tag,配置 origin,使用固定工具,并且暂存/输出 目录尚不存在。未打标签的候选版应使用 Snapshot 路径审核。

镜像归一化

底层 packaging/image-pipeline/build.sh 只接受显式本地 qcow2,不下载也不上传。它复制并 哈希源文件,强制 qcow2 解析,拒绝 Backing/External/Encryption/未知 Feature,运行 qemu-img check,并可在显式 QEMU Sandbox 中做无网络 Offline Guest Mutation。 UID/GID 88 冲突会拒绝,不会含糊改写。

build-official.py 为 Debian 12/13、Rocky Linux 8/9 的 amd64/arm64 目标增加固定、 摘要锁定的 Wrapper。它只允许获取锁定的源镜像与离线软件包输入,输出未签名的 testing Candidate,并可组装独立候选仓库。真机 Smoke、双构建比较、生产签名、上传与 Catalog 激活仍是后续门禁。

Catalog 逐字节导出命令:

go run ./tools/catalogexport /absolute/new/catalog.json

导出器原子写入,拒绝已存在的输出路径。make catalog-sign 与 make catalog-verify 使用 Catalog Minisign 密钥对,生产私钥不进入源码或 CI。应用 checksum 不能替代 Catalog 签名。

证据纪律

设计说明实现取舍,当前状态记录验证结果。每条状态结论应说明 日期、宿主、路径与剩余检查;源码变更需要相应验证。