9.7 KiB
UniDesk CLI Reference
UniDesk 的统一 CLI 入口是根目录 scripts/cli.ts,运行方式固定为 bun scripts/cli.ts <command>。CLI 默认输出 JSON,所有成功和失败路径都必须向 stdout 写出结构化对象,避免无输出造成状态不可观测。
Command Model
help输出命令索引,适合作为交互式入口。--main-server-ip <ip> <command>默认通过公网 frontend 登录态调用主 server 的同源 API 代理,不要求计算节点持有主 server SSH key;显式提供--main-server-key或--main-server-transport ssh时才使用旧 SSH 传输。config show读取并校验根目录config.json,不从环境变量、默认值或隐藏文件静默补配置。check执行配置校验、文件存在性检查、scripts/TypeScript 检查、src/components/TypeScript 检查和 Docker Compose 配置检查。server start创建异步 job,在后台执行 Docker 构建和启动;命令本身只负责返回 job id、日志路径和启动命令。server stop创建异步 job,在后台停止固定 Compose project 中的全部 UniDesk 服务。server status查询公开端口、内部端口、Compose 容器、core/frontend/provider/database 健康检查和访问 URL。server logs返回logs/文件日志和 Docker 容器日志的尾部,默认限制输出大小,避免日志爆炸。server rebuild <backend-core|frontend|provider-gateway|todo-note>创建异步 job,先构建目标服务镜像,构建成功后只按 Compose project/service label 移除该服务旧容器,再用--no-deps启动目标服务;该命令用于替代手工删除容器的兜底流程,其中todo-note只重建主 server 承载的 Todo Note 后端,不会重建或删除 database 命名卷。ssh <providerId> [ssh-like args...]通过 backend-core 内网 WebSocket broker 和 provider-gateway 的 Host SSH / WSL SSH 维护桥连接目标节点;无后续参数时进入远端登录 shell,有后续参数时按 ssh 远端命令体验执行并返回远端 exit code。microservice list/status/health/proxy通过 backend-core 内网 API 管理挂载在计算节点 Docker 中的 microservice;health和proxy会走真实 backend-core -> provider-gateway -> 节点本机后端链路,proxy对超大 body 默认输出有界预览,规则见docs/reference/microservices.md。job list与job status查询.state/jobs/文件系统状态,是异步命令的可观测入口。debug health、debug dispatch与debug task走真实内部 core、WebSocket、数据库、provider、系统指标、Docker 状态和 Host SSH 维护桥流程,只用于开发调试,不写入TEST.md的正式验收步骤。e2e run使用 publicHost 派生的公开 frontend/provider ingress URL,并通过 Docker 内网验证 core API、PostgreSQL、provider self-connection、系统指标曲线、Docker 状态快照、provider.upgrade 预检和 Playwright 前端页面,是交付前的自动化 E2E 门禁;CLI 默认输出 check 状态摘要,完整诊断写入resultPath。
Async Job State
长时操作采用 Fire-and-Forget 模式:CLI 创建 .state/jobs/{jobId}.json,后台进程执行真实命令,并将 stdout、stderr 分别写入 .state/jobs/{jobId}.stdout.log 与 .state/jobs/{jobId}.stderr.log。调用者通过 bun scripts/cli.ts job status <jobId> 查询进度和尾部输出。
server rebuild 与 server start、server stop 一样必须通过 job 状态确认结果。重建 frontend 的标准流程是运行 bun scripts/cli.ts server rebuild frontend,随后轮询 bun scripts/cli.ts job status latest 到 succeeded,再用 server status 或 e2e run 验证公网 frontend;重建 Todo Note 后端使用 bun scripts/cli.ts server rebuild todo-note,随后用 microservice health todo-note 和 microservice proxy todo-note /api/instances 验证。不得把 docker rm 手工兜底当成正式交付步骤。
Output Contract
每条命令的最外层 JSON 包含 ok、command 和 data 或 error。失败时 CLI 设置非零退出码,但仍然输出 JSON 错误对象;错误对象应包含 name、message 和可用的 stack。
microservice proxy 是面向人工验证的私有后端读取入口。正式写入型 microservice 操作由 frontend 同源代理或 E2E 直接调用 backend-core 完成,并由 config 中的 allowedMethods 限制;CLI proxy 默认仍作为 GET/HEAD 读取验证入口。为了避免 Pipeline snapshot 这类超大业务 JSON 造成 CLI 输出爆炸,响应 body 超过默认阈值时会返回 bodyOmitted=true、bodyPreview、bodyBytes 和 rawHint;需要完整 body 时显式添加 --raw,或用 --max-body-bytes <N> 调整预览阈值。正式 frontend 展示仍应优先使用业务控件和 __unideskArrayLimit 这类展示级裁剪参数,而不是默认倾倒完整 JSON。
Debug Contract
debug 子命令必须复用真实模块与真实端点,禁止维护平行实现。debug health 会摘要展示 /api/nodes/system-status 和 /api/nodes/docker-status,避免输出完整快照造成信息爆炸。debug dispatch 会在 backend-core 容器内调用内部 /api/dispatch,core 再通过 WebSocket 将 docker.ps、provider.upgrade、host.ssh、microservice.http 或 echo 任务下发给 provider gateway,因此它可以验证核心调度闭环,同时不需要公开 core REST API。provider.upgrade 默认使用 mode: "plan" 预检;需要验证一键升级时必须显式加 --mode schedule,并通过 --wait-ms 或 debug task 确认任务进入 succeeded、result 中包含 updater 容器信息和 policy: "always-enabled"。host.ssh 默认使用 mode: "probe" 做短超时维护桥自检;需要执行明确命令时使用 --ssh-command 进入 mode: "exec",并配合 --wait-ms 和 debug task 查看 stdout、stderr、exitCode 与 probeLine。microservice.http 只用于开发调试 provider-gateway 私有 HTTP 代理,正式用户入口应使用 microservice CLI 或 frontend 页面。
SSH Command
ssh <providerId> [ssh-like args...] 是面向人的终端透传入口,不包装 JSON 输出。CLI 会在宿主机启动一个 docker exec -i unidesk-backend-core bun -e ... broker,broker 只连接 backend-core 的 Docker 内网 /ws/ssh,core 再把 stdin/stdout/stderr 流量通过目标 provider 的既有 WebSocket 转发到 provider-gateway,provider-gateway 最终执行维护用 ssh -tt 连接宿主或 WSL sshd。该入口不新增 core 公网端口,不暴露 database,也不改变 frontend/provider ingress 之外的公网边界。
bun scripts/cli.ts ssh D518 应表现为登录 D518 WSL 的 shell;bun scripts/cli.ts ssh D518 hostname 应像 ssh D518 hostname 一样只输出远端命令结果并返回远端 exit code。Provider ID 前的目标选择由 UniDesk 节点清单决定,-p、-i、-l、-o 等传统 ssh 传输参数由 provider-gateway 部署配置统一管理,CLI 会兼容性消费这些参数但不会覆盖节点侧维护桥配置。
core 只允许声明了 host.ssh capability 的 provider 使用 ssh 透传或 host.ssh dispatch;旧 provider 不支持该能力时必须快速失败并输出错误,不能把未知命令误判成 echo 成功。
Remote Main Server Passthrough
--main-server-ip 是一个全局前缀,必须放在需要透传的命令同一次调用中,例如 bun scripts/cli.ts --main-server-ip 74.48.78.17 debug health。默认传输是公网 frontend:本地 CLI 读取本仓库 config.json 中的 frontend 登录账号密码,登录 http://<ip>:<frontendPort>/ 获取 HttpOnly session cookie,然后通过 frontend 的 /api/* 同源代理访问 backend-core 内网 API;因此计算节点只需要能访问公网 frontend,不需要主 server SSH key,也不需要打开 backend-core REST API 或 PostgreSQL 端口。
默认 frontend 传输支持 debug health、debug dispatch、debug task、microservice list/status/health/proxy 和 ssh <PROVIDER_ID> <remote-command>。其中 ssh 的 remote frontend 传输使用 host.ssh dispatch 执行有界远端命令,适合 ssh D601 hostname 这类自测;交互式登录 shell 仍应在主 server 本机 CLI 使用,或显式切换到旧 SSH 传输后在主 server 上执行。若确实需要旧行为,可使用 --main-server-key <key> 或 --main-server-transport ssh,这时 CLI 会通过 SSH 登录主 server 的 --main-server-root 目录执行同一个 bun scripts/cli.ts <command>。
计算节点可以用该入口测试自身的远程升级闭环,而不需要在计算节点公开 core REST API 或 database。标准顺序是:先运行 bun scripts/cli.ts --main-server-ip 74.48.78.17 debug health 确认主 server 看到当前 Provider 在线,且该 Provider labels 中 unideskCapabilities 包含 host.ssh、hostSshConfigured=true、hostSshKeyPresent=true;再运行 bun scripts/cli.ts --main-server-ip 74.48.78.17 debug dispatch <PROVIDER_ID> provider.upgrade --mode schedule --wait-ms 15000 触发真实 provider.upgrade;随后再次运行 debug health 确认节点重新上线;最后运行 bun scripts/cli.ts --main-server-ip 74.48.78.17 debug dispatch <PROVIDER_ID> host.ssh --wait-ms 15000 和 bun scripts/cli.ts --main-server-ip 74.48.78.17 ssh <PROVIDER_ID> hostname 验证 SSH 透传能力。provider-gateway 新部署或升级后没有完成这组 remote CLI 自测,不能视为交付完成。
远程透传的安全边界是公网 frontend 登录态和 frontend 到 backend-core 的内网代理;不要把 provider token、数据库端口或 backend-core REST API 暴露给计算节点。旧 SSH 传输只作为兼容路径保留,不得把“必须提供主 server SSH key”作为计算节点自测的前置条件。