跳转到主要内容

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

返回本页常规视图.

开始使用

用 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 - 快速上手

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

安装

本教程以 Barn 0.9.0 发布候选为准。当前请先从源码构建; 以下发行包和 Homebrew 命令在 0.9.0 发布、Formula 更新之后使用,不能把文档中的链接 当作已经发布的证明。进度见当前状态。

Barn 不兼容旧开发版本:只识别 barn.yml、BARN_* 与 ~/.barn 等新名称, 不读取或迁移旧状态,不提供旧命令别名。内部旧环境应先停机并保留需要的数据, 然后按新安装重新创建;不要把旧状态目录直接改名后继续使用。

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。

其他安装方式

发行包与 Homebrew Formula 就绪后,选择一种方式。以下 Linux 示例使用 amd64;ARM64 使用对应的 linux_arm64 文件。

Homebrew
brew install pgsty/infra/barn
barn version
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 解析为 [email protected];手动更新 Catalog 后 可能解析为其他版本,准确版本显示在 plan 和 status 中。

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

barn stop
barn start

使用完毕后销毁部署:

barn destroy

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

0.9.0 的新安装边界

Barn 0.9.0 是新名称下的首次发行。旧内部环境需要先停机,保留必要数据,然后重新创建 Barn 实验环境;不提供原位升级、旧命令别名或状态迁移。发行前从源码构建,发行后的安装 命令见本页开头。barn update 只更新镜像 Catalog,不更新 Barn 程序。

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

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

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 版本。

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: [email protected]。 显式 -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 安装。宿主文件传输与端口隧道见存储与访问。

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: [email protected]
  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 不会新建空目录替代。 修改已有节点的共享定义需要显式重建。完整磁盘与共享约束见配置参考。

6 - macOS 虚拟机

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

Barn 0.9.0 发布候选,尚未发布。 本页描述改名后的 barn mac, 使用全新 Barn 状态,不提供旧开发环境迁移。改名前的实机记录保留在 当前状态,不代表改名后已经完成同等验收。 请以实际运行的 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) · [email protected]
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。

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: [email protected]

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 结构始终校验。

镜像下载会重试临时故障,并接续中断的传输。自 0.7.0 起,选定官方端点无法提供镜像时, 两个官方仓库可以互相回退,仍须匹配同一 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 及发布前的独立验证要求见镜像流水线。

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/[email protected]
go install golang.org/x/tools/cmd/[email protected]
go install github.com/golangci/golangci-lint/v2/cmd/[email protected]
go install golang.org/x/vuln/cmd/[email protected]

确保 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 开头说明的镜像输入,不会下载测试镜像。

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

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/ 只是工作区构件,与上述宿主状态无关。