bcmr v0.6.0
online github↗
docs / 指南 / 远程复制 (SSH)

远程复制 (SSH)

BCMR 支持使用 SCP 风格语法通过 SSH 复制文件到远程主机或从远程主机复制文件。

语法

# 上传:本地 → 远程
bcmr copy local_file.txt user@host:/remote/path/

# 下载:远程 → 本地
bcmr copy user@host:/remote/file.txt ./local/

# 递归上传
bcmr copy -r local_dir/ user@host:/remote/path/

# 递归下载
bcmr copy -r user@host:/remote/dir/ ./local/

并行传输

使用 -P 参数同时传输多个文件:

# 4 个并行上传
bcmr copy -P 4 file1.bin file2.bin file3.bin file4.bin user@host:/remote/

# 递归上传,8 个 worker
bcmr copy -r -P 8 ./large_dataset/ user@host:/data/

# 并行下载
bcmr copy -P 3 user@host:/data/a.bin user@host:/data/b.bin ./local/

默认并行数通过 [scp] parallel_transfers 配置(默认:4)。使用 -P 1 或小量传输时按顺序执行。

TUI 和纯文本模式均会显示每个 worker 的状态:

Uploading: [████████░░░░░░░░░░░░░░░░░░] 42% [3/4w]
150 MiB / 350 MiB | 45.5 MiB/s | ETA: 04:32
[1] large.iso 53% | [2] backup.tar 78% | [3] data.csv 12% | [4] idle

压缩

BCMR 有两套独立的压缩层,请区分:

SSH 层(传统 SCP 路径)

远端没有安装 bcmr,传输回退到 SCP 时,SSH 传输层可以用 zlib 压缩。在 [scp] 中配置:

行为
"auto"按扩展名判断,可压缩字节 >30% 时启用压缩(默认)
"force"始终启用 SSH 压缩
"off"不压缩

auto 模式下,已知压缩格式(.gz.zip.mp4.jpg 等)被视为不可压缩。当大部分数据已经是压缩格式时,跳过压缩以避免 CPU 开销。

线路层(serve 协议,--compress

双方都能说 serve 协议 时,握手阶段协商出每块用 LZ4 还是 Zstd 压缩。这是独立于并快于 SSH 自带的 zlib — Zstd-3 在源码风格文本上达到 ~320 MB/s 编码、~5× 缩减,zlib 的吞吐只有它的约 1/10。

--compress 模式客户端通告的 caps协商结果
auto(默认)LZ4 + Zstd双方都有 → Zstd-3;否则 LZ4;都没有 → 原始
zstd仅 Zstd服务端也有 → Zstd-3;否则原始
lz4仅 LZ4服务端也有 → LZ4;否则原始
none/off只发原始 Data

每个 4 MiB 块会自动判断是否跳过压缩 — 编码后体积超过原始 95% 就直接发原始数据,这样已经压缩过的文件(.jpg.zst/dev/urandom)开启压缩几乎没有代价。真实链路上的压缩比和吞吐见 Wire Protocol 消融实验

Serve 协议(加速传输)

当远端也安装了 bcmr 时,传输自动使用 bcmr serve 协议 — 通过单个 SSH 连接的二进制帧协议。消除逐文件 SSH 进程开销,并支持服务端哈希计算。

远端没有 bcmr 时自动回退到传统 SCP。

在远端安装 bcmr

# 部署 bcmr 到远程主机
bcmr deploy user@host

# 自定义安装路径
bcmr deploy user@host --path /usr/local/bin/bcmr

bcmr deploy 自动检测远端 OS 和架构。相同平台时直接传输本地二进制文件,不同平台时从 GitHub Releases 下载对应版本。

Serve 协议优势

传统 SSHServe 协议
连接建立每个文件一个进程单个持久连接
文件列表ssh find(shell 解析)二进制 LIST 消息
哈希校验需传回数据到本地服务端直接计算 BLAKE3
上传校验需重新下载校验服务端返回写入后的哈希
单文件开销~50ms(进程启动)~0.1ms(消息帧)

校验远程传输

# 上传并校验完整性
bcmr copy -V local_file.txt user@host:/backup/

# 使用 serve 协议时,服务端在写入后计算哈希并返回
# 无需重新传输数据即可完成校验

内容寻址去重(CAP_DEDUP

serve 协议自带块级去重:≥ 16 MiB 的 PUT 会先交换每个 4 MiB 块的 BLAKE3 哈希,服务端只要那些不在本地内容寻址存储(CAS)里的块。CAS 路径由 BCMR_CAS_DIR / BCMR_CAS_CAP_MB 控制。

对每个够大的文件 PUT 自动生效 — 不需要额外 flag 启用。收益在“同一个构建产物反复上传”(开发循环)这种场景最明显:第二次上传跳过服务端已经有的所有块。

# 第一次:整个 64 MiB 都走线路
bcmr copy build/artifact.bin user@host:/deploy/

# 第二次:每个块都命中 CAS,实际线路字节数接近 0
bcmr copy build/artifact.bin user@host:/deploy/alt-name.bin

协议时序见 去重实验

快速模式(--fast

用"服务端省 CPU"换取跳过服务端 BLAKE3:

# 服务端 Ok 响应里 hash 为 None。
bcmr copy --fast user@host:/big.bin ./local.bin

# 跟 -V 组合:客户端重新 hash 目标文件
bcmr copy --fast -V user@host:/big.bin ./local.bin

服务端是 Linux 且 --compress=none 同时生效时,--fast 额外启用 splice(2) 做 file → stdout 零拷贝。splice 实现 目前并不是所有场景都更快--fast 诚实记录了这一权衡,详情看 Internals。

默认关闭 — --fast 是显式放弃服务端完整性校验。

工作原理

  • 使用现有的 SSH 配置(~/.ssh/config、密钥等)
  • 在开始传输前验证 SSH 连接
  • Serve 模式:通过 SSH 启动远端 bcmr serve,通过 stdin/stdout 的二进制协议通信
  • 传统模式:通过 ControlMaster 复用 SSH 连接,并行 worker 使用独立 TCP 连接
  • 通过 SSH 流式传输数据并追踪进度
  • 支持上传和下载两个方向

路径检测

BCMR 通过 [user@]host:path 格式检测远程路径。以下模式被识别为本地路径,不会触发远程模式:

  • 绝对路径(/path/to/file
  • 相对路径(./file../file
  • 主目录(~/file
  • Windows 盘符(C:\file