mote 命令
摘要
介绍 `mote`,一个 Go 命令行工具,可通过 SSH、Tailscale 或其他机制连接远程机器,以运行命令和交叉编译的 Go 测试,并支持上传文件以及与 `go run`/`go test` 集成。
<p><a href="https://lobste.rs/s/gblmih/mote_command">评论</a></p>
查看缓存全文
缓存时间: 2026/08/06 06:06
# mote 命令 - rsc.io/cmd/mote - Go Packages
来源:https://pkg.go.dev/rsc.io/cmd/mote
Mote 连接到远程机器并运行命令,尤其是交叉编译的 Go 测试。它可以通过多种机制连接:SSH、Gomote、基于 Tailscale 的 TCP 以及经过认证的直接 TCP。
用法:
```
mote [-u path]... [@name] cmd [args...]
mote alias [name [URL]]
mote clean
mote close [URL]
mote go-setup
mote login URL
mote serve URL
mote version
```
#### 运行程序¶ (https://pkg.go.dev/rsc.io/cmd/mote#hdr-Running_Programs)
最简单的 mote 命令指定一个主机和要运行的命令:
```
% mote @ssh://kremvax hostname
kremvax.uucp
%
```
在命令中,ssh://kremvax 是一个表示要使用的服务器的 URL。下面的“使用 SSH”一节说明了如何设置 kremvax。
一个更有趣的例子是上传并运行交叉编译的 Go 二进制文件。假设 kremvax 是 x86-64 Linux 系统:
```
% GOOS=linux GOARCH=amd64 go build $(go env GOROOT)/test/helloworld.go
% mote @ssh://kremvax ./helloworld
hello world
%
```
当命令名包含斜杠时,Mote 会将其视为要上传的文件:./helloworld 会被上传,而 hostname 不会。名称的解析方式与在本地运行相同,因此在 Windows 上,“mote ./strings” 会上传并运行 `./strings.exe`。
#### 上传附加文件¶ (https://pkg.go.dev/rsc.io/cmd/mote#hdr-Uploading_Additional_Files)
命令会在一个包含本地目录名的远程临时目录中运行。例如,考虑:
```
% cd /home/rsc/src/myprog
% mote @ssh://kremvax ../testprog
```
在本例中,远程命令可能会在 /tmp/mote-123/home/rsc/src/myprog 中运行,testprog 被上传到 /tmp/mote-123/home/rsc/src/testprog。
可重复的 `-u` 标志指定要上传到远程临时目录树中的附加文件或目录。例如,如果某个测试二进制文件需要 testdata:
```
% cd /home/rsc/src/mypkg
% GOOS=linux GOARCH=amd64 go test -c
% mote -u ./testdata @ssh://kremvax ./mypkg.test
PASS
%
```
`-t` 标志会上传 testdata、../testdata、../../testdata 等存在的目录,直到当前 Go 模块根目录:
```
% mote -t @ssh://kremvax ./mypkg.test
```
#### 服务器别名与服务器选择¶ (https://pkg.go.dev/rsc.io/cmd/mote#hdr-Server_Aliases_and_Server_Selection)
“mote alias”命令为 URL 定义别名:
```
% mote alias kremvax ssh://kremvax
% mote @kremvax ./mypkg.test
PASS
%
```
运行“mote alias name”会展开别名:
```
% mote alias kremvax
ssh://kremvax
%
```
不带任何参数运行“mote alias”会列出所有已知别名:
```
% mote alias
kremvax ssh://kremvax
linux-amd64 ssh://kremvax
%
```
每次运行 mote 命令时,它都会发现远程系统的 GOOS 和 GOARCH。如果还没有名为 $GOOS-$GOARCH 的别名,mote 会添加一个指向该系统的别名。在此示例中,mote 定义了一个 linux-amd64 别名。
如果省略“@server”,mote 会依次尝试三种后备方式:
- 设置了 $MOTE 时使用 $MOTE。
- 设置了 $GOOS 和 $GOARCH 时使用 $GOOS-$GOARCH。
- 如果可能,根据要上传的二进制文件推导出 $GOOS-$GOARCH,然后使用 $GOOS-$GOARCH。
下面演示全部三种方式:
```
% MOTE=kremvax mote ./mypkg.test
% GOOS=linux GOARCH=amd64 mote ./mypkg.test
% mote ./mypkg.test
```
#### Go Run 与 Go Test 集成¶ (https://pkg.go.dev/rsc.io/cmd/mote#hdr-Go_Run_and_Go_Test_Integration)
Go 工具链通过查找 shell 路径中名为 go_$GOOS_$GOARCH_exec 的运行器来处理交叉编译二进制的“go run”和“go test”。要为所有尚没有运行器的 GOOS-GOARCH 组合创建运行器脚本:
```
% mote go-setup
installed 10 hooks in /home/rsc/bin
% mote go-setup
no hooks left to install
%
```
运行器脚本就是对参数应用“mote -t”:
```
% cat /home/rsc/bin/go_linux_amd64_exec
#!/bin/sh
exec mote -t "$@"
%
```
脚本没有指定服务器,因此 mote 会使用上面列出的后备方式。在命令行上进行交叉编译会在“go test”传给脚本的环境中设置 $GOOS 和 $GOARCH,从而选择目标系统的别名;如果改用“go env -w”,这些变量会保持未设置,mote 会从测试二进制文件中读取它们。无论哪种方式,隐含的服务器都是 $GOOS-$GOARCH 别名。
为单个命令设置 $MOTE 可以覆盖该选择,指定要使用的别名或 URL:
```
% GOOS=linux GOARCH=amd64 go test strings
PASS
% MOTE=kremvax GOOS=linux GOARCH=amd64 go test strings
PASS
% MOTE=ssh://kremvax GOOS=linux GOARCH=amd64 go test strings
PASS
%
```
当有多个服务器运行相同的 $GOOS-$GOARCH 时,设置 $MOTE 会很有用。
#### 使用 SSH¶ (https://pkg.go.dev/rsc.io/cmd/mote#hdr-Using_SSH)
要通过 SSH 使用 mote,需要在客户端和服务器上编译并安装 mote,并确认它已加入服务器的 PATH:
```
% go install rsc.io/cmd/mote@latest
% ssh kremvax 'go install rsc.io/cmd/mote@latest && mote version'
% mote @ssh://kremvax hostname
kremvax.uucp
%
```
Mote 以启用持久连接且超时时间为 30 分钟的方式运行 ssh,以便重复使用 mote 可以共享一个长期运行的 ssh 连接。具体而言,它运行:
```
ssh \
-o 'ControlMaster auto' \
-o 'ControlPath ~/.ssh/sockets/mote-%r@%h-%p' \
-o 'ControlPersist 1800' \
kremvax \
mote serve -
```
#### 使用 Tailscale¶ (https://pkg.go.dev/rsc.io/cmd/mote#hdr-Using_Tailscale)
通过 SSH 使用 mote 要求服务器可直接访问。Mote 内置的 Tailscale 库消除了这一要求。
要通过 Tailscale 提供 mote 服务:
```
mote serve tail://servername
```
其中 servername 是所需的服务器名称。
要运行远程命令:
```
mote @tail://servername hostname
```
客户端或服务器第一次使用 Tailscale 时,需要连接到 tailnet。Mote 会提示输入 Tailscale 认证密钥,然后使用该认证密钥进行注册并获取凭据。它会缓存这些凭据以供后续运行复用。
要创建认证密钥,请打开 Tailscale 管理控制台的“Keys”页面(https://login.tailscale.com/admin/settings/keys),然后点击“Generate auth key”。Mote 使用标签“tag:mote”注册,因此在生成密钥之前,请在 tailnet 策略文件的“tagOwners”部分定义 tag:mote,然后在密钥生成表单上选择 tag:mote。带标签的节点不会附加会过期的人类身份,而且该标签使为 mote 服务器编写网络策略规则变得容易。
服务器在 tailnet 上注册为 mote-servername,客户端注册为 mote-clientname,其中 clientname 是本地主机名的第一个元素。要设置不同的客户端名称,请运行“mote login tail://clientname”。一台机器只会注册一个节点:如果它已经以某个名称登录(无论是通过“mote login”还是“mote serve”),mote 都会使用该登录身份,而不会再次注册。
系统注册后,无论是通过之前的“mote serve”还是显式的“mote login”,“mote serve tail://servername”都可以简写为“mote serve tail:”。
启动 Tailscale 节点需要几秒钟,而 Tailscale 并不期望节点频繁地上下线,因此 mote 会像 ssh 保持连接一样,让节点在后台守护进程中持续运行。第一个需要 tailnet 的 mote 会启动该守护进程;后续的 mote 会发现并复用它,因此只有第一个命令需要为连接付出代价。守护进程在空闲 30 分钟后退出。
Mote 的 Tailscale 客户端完全内置于 mote 二进制文件中,不会重新配置或影响主机网络协议栈。机器上的其他程序不会使用由 mote 管理的 Tailscale 连接。
#### 使用直接 TCP¶ (https://pkg.go.dev/rsc.io/cmd/mote#hdr-Using_Direct_TCP)
如果客户端可以连接到服务器,最简单的机制就是直接 TCP。对于直接 TCP,URL 的形式为 tcp://host:port。客户端和服务器共享一个密码,用于认证连接,并在此基础上建立加密会话。
运行“mote login URL”会提示输入用于某个服务器的密码,并将其保存以供后续运行使用:
```
% mote login tcp://kremlsun:6683
password for tcp://kremlsun:6683:
mote: wrote password for tcp://kremlsun:6683 to /home/rsc/.config/mote/password.txt
%
```
每台机器都会保存它用来指代服务器的 URL 所对应的密码,因此客户端和服务器可以以不同的方式命名同一个服务器。服务器使用它所服务的 URL 登录,然后提供服务:
```
% mote login tcp://:6683
password for tcp://:6683:
mote: wrote password for tcp://:6683 to /home/rsc/.config/mote/password.txt
% mote serve tcp://:6683
mote: serving tcp://kremlsun:6683
```
主机可以省略(tcp://:port),表示监听所有接口。mote 命令在开始提供服务时会打印一个完整的 URL。
要运行远程命令:
```
% mote @tcp://kremlsun:6683 hostname
kremlsun.arpa
%
```
每个服务器都有自己的密码:登录第二个服务器时会添加一条记录,而不会替换第一条记录。
#### 使用 Gomotes¶ (https://pkg.go.dev/rsc.io/cmd/mote#hdr-Using_Gomotes)
Go 项目运行一个名为 gomotes 的自定义远程执行设施,用于访问 Go 自身测试所使用的各种构建器。如果在 PATH 中找到了 gomote 命令,mote 可以使用这些服务器。
要运行远程命令:
```
% mote @gomote://gotip-linux-amd64 hostname
TODO
%
```
(如果你最近没有使用过 gomote,可能需要先运行“gomote login”。)
mote 客户端会在创建 gomote 后安装并启动 mote 服务器。
如果在 PATH 中找到了 gomote 命令,mote 会根据需要创建由 gomotes 支持的 GOOS-GOARCH 别名。例如:
```
% mote go-setup
% mote alias linux-arm64
mote: no alias for linux-arm64
% GOOS=linux GOARCH=arm64 go test strings
PASS
% mote alias linux-arm64
gomote://gotip-linux-arm64
%
```
#### 关闭服务器¶ (https://pkg.go.dev/rsc.io/cmd/mote#hdr-Closing_Servers)
每种传输方式都会让连接保持打开状态,以供下一条 mote 命令使用,超时时间为 30 分钟。要提前关闭这些连接,请使用“mote close URL”:
```
% mote close ssh://kremvax
% mote close tail:
% mote close gomote://gotip-linux-amd64
mote: destroyed gomote user-gotip-linux-amd64-0
%
```
不带 URL 运行“mote close”会关闭所有内容:每个共享的 ssh 连接、每个本地 Tailscale 守护进程,以及 mote 创建的每个 gomote 实例。
```
% mote close
mote: closed shared ssh connection to kremvax
mote: stopped tailscale daemon for mote-mac
mote: destroyed gomote user-gotip-linux-amd64-0
%
```
#### 配置¶ (https://pkg.go.dev/rsc.io/cmd/mote#hdr-Configuration)
Mote 将配置存储在用户配置目录下的 mote 子目录中。例如:
- Linux 上的 /home/rsc/.config/mote/
- macOS 上的 /Users/rsc/Library/Application Support/mote
- Windows 上的 C:\Users\rsc\AppData\Local\mote\
在该目录中:
- aliases.txt 包含别名定义,每行一个别名。
- password.txt 包含与 tcp:// 服务器共享的密码,由“mote login”写入:每行一个服务器,包含服务器 URL 和密码,用空格分隔。
- tail-name/ 是一个目录,保存 tail://name 的登录凭据,以及持有该节点的守护进程的服务套接字、锁和日志。
Tailscale 凭据和 tcp:// 密码都以明文存储,仅受配置目录及其文件的权限保护。
设置 $MOTECONFIG 可以覆盖配置目录的位置。
mote 服务器会在用户缓存目录的 mote/cache 子目录中维护一个内容寻址的上传文件缓存(例如 Linux 上的 /home/rsc/.cache/mote/cache)。设置 $MOTECACHE 可以覆盖缓存目录的位置。每次命令完成后,服务器都会删除超过三小时未使用的缓存文件。运行“mote clean”会删除整个缓存。
相似文章
mvm - 一个快速的 Go 虚拟机
mvm 是一个快速、可移植的 Go 虚拟机,支持直接从源码运行 Go 程序、嵌入 Go 解释器,并包含 REPL、调试器和标准库。
CodeMote
CodeMote 是一款 iPhone 应用,可让你远程控制像 Claude Code 和 Codex 这样的 AI CLI 代理。
TailMux
TailMux 允许用户同时连接多个 Tailscale 网络,无需切换或使用虚拟机。
@seclink: 小米发布了 mimo-code ,可以下载代码用起来
小米发布了 MiMoCode,一个具有跨会话记忆的开源 AI 编码助手,可在 GitHub 上获取,并通过一行命令或 npm 安装。
[开源] 我用 Go 编写了一个完整的 Git MCP 服务器,不是简单地封装 bash。它使用了 tree-sitter,处理真正的底层操作(write-tree),并且 100% 本地运行。
git-courer 是一个用 Go 编写的完整 Git MCP 服务器,它使用 tree-sitter 进行语义代码分析,通过结构化 JSON 进行通信,支持 13 个客户端,并以本地优先的方式运行。