克隆树莓派系统后,如何拆分两台设备的系统身份

背景 一套已经配置好的树莓派系统被完整复制到另一张存储卡上,随后分别在两台树莓派设备上启动。这样做可以节省大量重复配置时间,尤其适合系统中已经预先配置好远程访问、网络脚本、代理服务、Web 服务和若干常驻服务的情况。 不过,完整克隆系统也会带来一个明显问题:两台设备虽然硬件不同,但系统内部身份可能完全相同。 如果不处理,后续可能出现: 因此,在两台设备正式长期运行前,需要先把系统身份拆分开。 克隆系统后需要处理哪些身份信息 克隆系统后,至少需要检查和处理以下内容: 其中,最基础的三项是: 这三项分别对应: 只改主机名是不够的。如果 machine-id 和 SSH Host Key 仍然相同,两台设备在系统层面和安全身份层面仍然带有克隆痕迹。 第一次只改主机名为什么失败 一开始使用了常规方式修改主机名: 并同步修改: 当时看起来已经成功,但重启后主机名又恢复成旧值。 这说明问题并不在 hostnamectl 本身,而是系统启动过程中还有其他组件在覆盖主机名。 进一步检查发现,这套系统启用了 cloud-init。在该类系统中,主机名可能不是只由 /etc/hostname 决定,而是还会受到启动分区中的 cloud-init 配置影响。 关键位置包括: 如果启动分区的 user-data 中仍然写着旧主机名,同时 cloud-init 没有设置为保留当前主机名,那么重启后系统可能再次把主机名改回旧值。 因此,正确做法不是只改 /etc/hostname,而是要同时处理 cloud-init 的源头配置。 正确修改第一台设备主机名 假设第一台设备的新主机名为: 在 root 用户下,可以一次性执行: 重启后确认: 目标状态是: 这样,主机名才算真正持久修改成功。 重新生成 machine-id …

使用 Raspberry Pi Imager 建立分区后,通过 rsync 还原树莓派系统备份

背景 树莓派系统备份有两种常见方式:一种是直接使用镜像工具进行整卡复制,另一种是以目录形式保存完整 Linux 根文件系统。后者的优点是灵活,可以在不同容量的 SD 卡之间迁移,也方便排除临时文件、伪文件系统和缓存内容。 本次操作的目标是:使用 Raspberry Pi 官方写盘工具先写入一个新的可启动系统,让它自动建立 SD 卡分区结构;然后保留这个分区结构,删除新系统文件,再把已有的完整系统备份同步进去。最后修改新 SD 卡的 UUID,使系统能够正常启动。 这种方式适合以下场景: 基本思路 整个流程可以概括为: 其中最关键的地方是:还原文件之后,不能继续使用旧备份里的 UUID。必须把 fstab 和 cmdline.txt 中的 UUID 改成当前 SD 卡实际分区的 UUID。 事前确认 假设: 其中: 备份目录应当是完整的 Linux 根文件系统,顶层通常能看到: 如果备份使用的是较新的 Raspberry Pi OS 或 Ubuntu for Raspberry Pi,启动文件通常位于: 对应地,启动分区应挂载到: 第一步:用 Raspberry Pi Imager 写入基础系统 …

把操作经验写入 TOOLS.md:AI 代理长期规则如何固化

本地 AI 代理系统真正进入长期使用阶段后,最重要的问题不再只是“它能不能完成任务”,而是“它以后会不会按照稳定、可预期、边界清楚的方式完成任务”。 一次迁移、一次修复、一次浏览器调用、一次误操作事故,如果只停留在当前对话里,很快就会消失。下一次再遇到类似场景,代理可能重新犯同样的错误。 因此,迁移完成后的一个重要收尾工作,是把经验写入长期规则文件。 在这个过程中,TOOLS.md 成为最关键的文件之一。 为什么需要长期规则 AI 代理和普通脚本不同。 普通脚本只会执行写死的逻辑。AI 代理则会根据自然语言指令、上下文、工具可用性和自己的推断来决定下一步操作。 这带来灵活性,也带来风险。 如果只告诉代理: 它可能会自己推断出很多没有被允许的做法: 这些推断未必是恶意的,但可能与实际使用场景冲突。 因此,长期规则的作用不是单纯记录“怎么做”,还要记录: 对长期运行的 AI 代理来说,负面边界和正向流程同样重要。 日期记忆不适合保存持续规则 很多代理工作区会有按日期排列的记忆文件,例如: 这类文件适合记录当天发生了什么: 但它们不适合作为长期规则的唯一来源。 原因是日期文件本质上是事件记录,而不是行为规范。代理以后要决定如何调用工具时,不一定会优先读取某一天的历史记录。 例如: 这条记录能说明事情发生过,但不能保证代理以后每次用浏览器都遵守这些规则。 因此,持续规则应该写入专门的规则文件。 为什么浏览器规则应该写入 TOOLS.md 在 OpenClaw 工作区中,不同 Markdown 文件承担不同职责。 抽象上可以这样划分: 远程浏览器/CDP 能力本质上是一个工具。它不是用户偏好,也不是人格设定,也不是普通历史记忆。 它包含: 所以它应该写入 TOOLS.md。 这能让代理在以后调用浏览器时,把它当作一个受约束的工具,而不是凭当前对话临时推断。 工具规则不只是命令 一个常见误区是把工具规则写成几条命令。 例如: 这还不够。 真正可长期使用的工具规则应该包含五个层次: 以远程浏览器为例,资源定义应包括: 使用前检查应包括: 正常启动流程应包括: …

迁移后的文件清理:用 sha256 审计安全删除 67325 个重复文件

主实例迁移完成后,旧主机上往往会留下大量重复文件。 这些文件看起来像“迁移残留”,但不能直接删除。因为旧主机上可能同时保留着几类不同性质的数据: 如果不加区分地删除旧工作区,很容易误删尚未迁移的项目、迁移后仍需要的扩展资源,或者旧主机上独有的备份文件。 因此,迁移后的文件清理不能靠“看目录名猜”,而应该靠审计结果决定。 本篇记录的是一次通过相对路径、文件大小和 sha256 hash 对比,安全删除旧主机重复文件的过程。 清理前的基本局面 迁移完成后,系统已经形成新的主从结构: 旧主机上的大部分工作区文件已经迁移到新主机,但不是全部。 其中有一个大型项目目录因为新主机存储容量不足,暂时继续保留在旧主机上,作为扩展项目使用。另一个浏览器/CDP 目录也属于外部工具资源,不属于本次工作区清理范围。 因此,清理前必须先确定排除范围。 不能清理的目录 迁移后文件清理首先要明确两类禁止触碰目录。 第一类是大型项目目录。 它因为容量原因没有迁移到新主机,仍然需要继续保留在旧主机上。如果清理脚本把它当成普通迁移残留,就会造成严重误删。 可以抽象表示为: 第二类是浏览器/CDP 专用目录。 这个目录用于远程浏览器能力,属于旧主机作为扩展资源主机的一部分,不是旧 OpenClaw 主实例残留。 可以抽象表示为: 因此,清理审计范围应该是: 这个边界非常重要。否则“清理旧工作区”很容易被误解成“删除旧主机上所有 OpenClaw 相关目录”。 为什么不能直接用 rsync –delete 迁移清理中,rsync –delete 看起来很诱人。它可以让两个目录快速变成一致状态。 但在这个场景中,它并不适合。 原因是旧主机上故意保留了一些新主机没有的内容。如果直接用 rsync –delete 或类似逻辑,就可能把旧主机独有但仍然需要的文件删除。 尤其是以下几类文件: 因此,本次清理不追求两个工作区完全一致,而是只删除那些已经被确认“新主机上有同名文件,且内容完全相同”的文件。 这比 rsync –delete 更保守,也更适合迁移后的分层清理。 审计方法:相对路径、大小和 sha256 安全清理的核心是生成两边文件清单。 对旧主机工作区生成 …

AI 代理误杀普通浏览器的事故复盘:权限边界必须写死

在本地 AI 代理系统中,浏览器自动化是一项非常有用的能力。代理可以打开网页、搜索信息、读取页面、协助登录后台、处理表单,甚至通过 CDP 控制完整浏览器。 但浏览器自动化也有一个明显风险:如果代理没有严格区分“自己可管理的浏览器”和“用户正在使用的普通浏览器”,它就可能误伤用户的真实桌面环境。 本篇记录的是一次典型的边界事故:AI 代理本来只应该打开和关闭自己的专用浏览器,却因为使用了过宽的进程匹配,把用户正常使用的普通 Brave 浏览器也关闭了。 这不是单纯的命令错误,而是一次权限边界设计错误。 背景:主实例和浏览器分离 迁移后的结构中,OpenClaw 主实例运行在常驻主机上,桌面浏览器运行在另一台桌面主机上。 浏览器调用链路大致是: 为了隔离用户日常浏览器和 AI 代理浏览器,桌面主机上准备了一个专用 profile: OpenClaw 只能使用这个专用 profile。用户日常使用的普通 Brave profile、普通窗口、普通标签页和普通会话,都不属于 OpenClaw 的管理范围。 从设计上看,这个边界是清楚的。 但事故说明:只靠“人知道边界”不够,必须让 AI 代理的规则和命令也严格遵守这个边界。 事故经过 最初的任务很简单:让 AI 代理在桌面主机上远程打开一个可见 Brave 窗口,用于测试浏览器/CDP 能力。 代理确实打开了一个新的可见窗口。 但在打开之前,它先关闭了桌面主机上原本已经打开的普通 Brave 窗口。 随后,又让代理关闭刚才打开的浏览器窗口。结果它在关闭时,再次把用户后来重新打开的普通 Brave 窗口关闭了。 也就是说,事故不是一次偶发误操作,而是在两个阶段都发生了边界错误: 这说明代理没有把“OpenClaw 专用浏览器”和“用户普通浏览器”区分开。 真正的问题:它管理了 Brave 进程整体 …

Saturn 如何调用 Mars 浏览器:SSH Tunnel、Brave CDP 与可见窗口

把 OpenClaw 主实例迁移到树莓派之后,一个问题很快出现:主实例已经在树莓派上运行,但完整桌面浏览器仍然在桌面 Linux 主机上。 树莓派适合承担长期在线的 OpenClaw gateway、消息通道和主工作区,但它并不适合作为完整图形浏览器主机。桌面机已经具备图形环境、浏览器、用户会话和更强的桌面交互能力,因此更适合继续提供浏览器/CDP 能力。 这就形成了一种分离式结构: 本篇记录的是:如何让运行在树莓派上的 OpenClaw,按需调用桌面机上的 Brave 浏览器。 为什么不直接在树莓派上运行浏览器 理论上,可以在树莓派上安装 Chromium 或 Brave,再让 OpenClaw 直接使用本机浏览器。但实际并不一定合适。 原因包括: 对一个长期运行的 AI 代理系统来说,主实例和浏览器并不一定要在同一台机器上。 更合理的结构是: 这样,树莓派保持轻量稳定,桌面机只在需要时提供浏览器能力。 CDP 是什么角色 CDP,即 Chrome DevTools Protocol,是 Chromium 系浏览器提供的远程调试和自动化接口。Brave 基于 Chromium,因此也可以通过 CDP 被自动化工具连接。 浏览器启动时指定 remote debugging 参数,例如: 浏览器就会在本机提供一个 CDP endpoint。访问: 如果返回包含 webSocketDebuggerUrl 的 JSON,就说明 …

清理旧 OpenClaw 实例:安装目录、systemd 服务和 shell 残留

OpenClaw 主实例迁移到新主机后,旧主机上的清理工作同样重要。 很多迁移事故并不是发生在复制文件时,而是发生在迁移之后:旧服务还在、旧命令还能执行、旧配置目录仍然存在、shell 里还保留 alias 或 PATH。表面上看主实例已经迁走,实际上旧主机仍然残留一个“半可用”的 OpenClaw 实例。 这种状态非常危险。因为一旦旧实例被误启动,就可能出现两个 OpenClaw 同时存在的情况: 清理旧实例的目标,不是简单删除几个目录,而是让旧主机彻底退出 OpenClaw 主运行链路。 旧实例清理的核心原则 迁移完成后,系统里应该只有一个 OpenClaw 主实例。 旧主机可以继续作为扩展资源主机,例如提供浏览器、图形环境、大型项目目录或临时计算能力,但它不应该再保留可启动的 OpenClaw gateway,也不应该再保留容易误用的 OpenClaw 命令入口。 清理的目标可以概括为: 最重要的是,不要让旧主机继续具备“像主实例一样启动 OpenClaw”的能力。 区分安装目录和状态目录 清理旧实例时,第一个容易混淆的问题是:OpenClaw 的安装目录和状态目录不是一回事。 常见结构大致如下: 软件安装目录通常包含 OpenClaw 程序本体、Node runtime、工具链、dist 文件等。状态目录则包含配置、session、插件状态、浏览器 profile、缓存、认证引用等内容。工作区则保存用户交互产生的文件、memory、projects、output、plans 等。 如果只删除状态目录,而保留安装目录和命令入口,旧实例仍然可能被启动。 如果只删除安装目录,而保留状态目录,旧配置、旧 session、旧浏览器 profile 和旧缓存仍然会留在系统里。 如果只清理 workspace,而不清理 systemd 服务,旧服务可能在某次登录或重启后继续尝试启动,并产生新的错误日志。 因此,清理旧实例必须同时检查三类内容: 停止旧 systemd …

迁移后的 OpenClaw 修复:插件、SecretRef、Dashboard 与历史会话

主实例迁移完成,并不意味着 OpenClaw 已经完全恢复到可用状态。 对一个本地 AI 代理系统来说,真正复杂的部分往往不在安装程序本身,而在迁移之后的状态修复:旧路径残留、插件注册状态、SecretRef 引用、消息通道、Dashboard 授权、历史会话索引等,都可能因为主机和路径变化而出现问题。 本篇记录的是 OpenClaw 主实例迁移到新的常驻节点后,如何逐步修复运行状态,并最终确认系统恢复正常。 迁移后最先暴露的问题:路径仍指向旧主机 迁移后,OpenClaw 的主状态目录和工作区已经转移到新主机,但部分内部记录仍然指向旧主机上的路径。 典型表现是:消息通道能够收到请求,但代理长时间卡在处理中,或者表现为“正在输入”,最终没有正常回复。 这类问题的根因通常不是模型不可用,也不是消息平台本身故障,而是 OpenClaw 内部仍然认为工作区位于旧路径。例如: 当 attestation、session snapshot、workspace state 等记录仍然引用旧路径时,OpenClaw 在处理任务时可能会尝试访问一个已经不存在的 workspace,从而导致任务无法继续。 因此,迁移后的第一步不是急着修插件,而是确认: 路径修复完成后,消息通道才恢复正常响应。 插件状态异常:目录存在,但 registry 不认识 迁移后另一个明显问题是插件 warning。 从文件系统看,相关插件目录可能已经随状态目录迁移过来,目录本身存在,权限也正常。但 OpenClaw 启动或进入 TUI 时仍然提示: 这说明问题不一定是插件文件缺失,而可能是插件 registry、host peer link 或 managed npm plugin 状态没有正确恢复。 这类问题比较容易误判。因为目录存在会让人以为插件已经安装完成,但 OpenClaw 运行时真正依赖的是它自己的插件注册和加载状态,而不仅仅是文件是否存在。 处理方式是使用 …

OpenClaw 主实例从桌面机迁移到树莓派:一次本地 AI 代理基础设施重构

本地 AI 代理最初往往只是一个“能跑起来”的工具:在桌面机上安装,接入模型,配置几个插件,再接入聊天渠道或浏览器能力。这个阶段的重点是验证可用性,而不是长期运行。 但当一个 AI 代理开始承担更多日常任务,例如消息通道响应、文件处理、浏览器辅助、系统状态检查、项目资料检索,它就不再只是一个临时工具,而会逐渐变成本地基础设施的一部分。此时,运行位置、可用性、状态目录、外部访问入口、权限边界和数据分工都会变得重要。 这次迁移的核心,就是把 OpenClaw 的主安装实例从一台桌面 Linux 主机迁移到一台树莓派上,让树莓派承担长期在线的主服务角色,而桌面机则退回为扩展资源主机。 迁移前的结构 迁移前,OpenClaw 主实例运行在一台日常使用的桌面 Linux 主机上。它同时承担多个角色: 这种结构在早期很方便。所有东西都在同一台机器上,路径简单,浏览器也直接可见,调试成本低。需要排查时,打开终端就能看到服务、配置和日志。 但随着 OpenClaw 逐渐变成一个长期使用的代理系统,这种结构的问题也越来越明显。 首先,桌面机不是理想的 24 小时在线主机。它可能重启、关机、休眠,也可能因为桌面环境、浏览器、图形会话或用户操作影响服务状态。 其次,桌面机上同时有用户日常使用的程序和 OpenClaw 的自动化任务。一旦 AI 代理具备操作浏览器、文件和系统命令的能力,就必须严格区分“代理可管理的资源”和“用户私人使用的资源”。 第三,桌面机上的 OpenClaw 历史安装路径、配置目录、浏览器 profile、systemd user service、shell alias、旧备份目录等内容逐渐混杂。继续在原地修补,会让整个系统越来越难判断边界。 因此,迁移的目标不是单纯“换一台机器运行”,而是重新划分职责。 迁移后的目标架构 迁移后的结构可以概括为: 也就是说,树莓派成为 OpenClaw 的主节点,桌面机只保留少量无法或不适合迁移的能力。 这种设计的好处是,主服务变得更加稳定。树莓派功耗低,适合常驻;桌面机可以继续作为高性能或图形资源节点,但不再承担 OpenClaw 主实例的核心状态。 为什么选择树莓派作为主节点 树莓派并不适合承载所有任务。它的存储容量、CPU 性能和 I/O 能力都有限,尤其不适合大型数据库、大型本地项目和图形浏览器长期高负载运行。 但它很适合承担以下角色: …

KDE Akonadi 登录阶段启动超时的排查与修复:一次由 kalendarac 引发的竞态问题

背景 某台 Arch Linux KDE Plasma 桌面系统在登录后检查用户级 systemd 服务状态时,发现曾经出现过 Akonadi 相关失败记录。Akonadi 是 KDE PIM 体系中的个人信息管理后端,常被 KMail、Kontact、KOrganizer、KAddressBook、日历提醒、联系人、邮件索引等组件使用。 问题的表面现象比较迷惑: 一开始能看到 Akonadi 相关失败;但随后执行: 又显示: 也就是说,systemd 认为某次 Akonadi 启动失败了,但 Akonadi 本身后来又确实运行起来了。 这类问题如果直接重建 Akonadi 数据库,很容易扩大风险。更合理的处理方式是先确认失败链路,再做最小可回退修复。 初始现象 用户级日志中可以看到类似记录: Akonadi 使用内置 MariaDB/MySQL 后端。日志中 mysqld 被 systemd 杀掉,说明失败并不是单纯的前端组件问题,而是 Akonadi 启动流程中包含的数据库进程被一并终止了。 系统级 unit 内容类似: 最初可疑点是 TimeoutSec=5sec。Akonadi 登录阶段启动时需要拉起 MariaDB、初始化数据库、注册 D-Bus …