bcmr v0.7.1
docs / 指南 / 遠端複製 (SSH)

遠端複製 (SSH)

BCMR 支援使用 SCP 風格語法透過 SSH 複製檔案到遠端主機或從遠端主機複製檔案。

語法

來源路徑中的星號

複製和移動支援本機及遠端來源路徑中的 *。直接呼叫 bcmr 時請加引號,讓 Shell 將模式原樣傳入:

bcmr copy 'mini_m2:/Users/snaix/Downloads/deecamp中期检查*' ~/Downloads/
bcmr copy 'host:~/reports/report*' ./downloads/

執行 eval "$(bcmr init zsh --cmd b)" 後,bcp、bmv 也支援不加引號的星號。產生的 noglob 別名只作用於這兩個包裝命令,不改變 zsh 的 NOMATCH 設定或其他命令。升級後需要重新初始化。

* 比對單一路徑層級內的零個或多個字元,不跨 /。隱藏檔案需明確以點號開頭;比對到目錄仍需 -r。無符合項目時在複製前報錯。已存在的精確路徑優先按字面處理,包括名稱本身含 * 的檔案;目的路徑一律按字面處理。僅 * 有模式含義,?、方括號和遞迴 ** 不作為額外運算子。多目的地操作共用一次展開的來源清單。

# 上傳:本機 → 遠端
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)。 Serve 模式的目錄批次最多使用這麼多條互相獨立的 SSH 工作階段。 即使 -P 更大,單檔上傳也只建立一條工作階段,因為正式路徑不會 為了分片而犧牲可見目標檔案的當機安全性。

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,傳輸回退到傳統 SSH 通道時,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 程序開銷,並支援伺服端雜湊計算。

目前線路協定版本為 v2,並刻意不接受 v1 的 PUT 語意。遠端沒有 bcmr 或協定版本不匹配時,bcmr 會顯示回退警告並使用傳統 SCP。

在遠端安裝 bcmr

# 部署 bcmr 到遠端主機
bcmr deploy user@host

# 升級系統安裝(互動式終端可輸入 sudo 密碼)
bcmr deploy user@host --path /usr/local/bin/bcmr --sudo

# 對多台伺服器套用相同選項,分別部署
bcmr deploy A100 4090 --path /usr/bin/bcmr --sudo

bcmr deploy 分別偵測每台伺服器的 OS 與架構。相同平台時直接傳輸本機執行檔,不同平台時從與本機版本號一致的 GitHub Release 下載對應檔案。

版本檢查與安裝後驗證均針對選定路徑(預設 ~/.local/bin/bcmr),不受 PATH 中另一份安裝的版本影響。安裝成功與略過結果都會顯示安裝路徑/版本,以及 PATH 實際選中的路徑/版本;若被另一份安裝遮蔽,會給出提示。使用 --path 可指定需要升級的那份安裝。

各伺服器依序獨立部署,某台失敗後仍繼續處理其他目標,最後彙總成功、略過與失敗結果;存在失敗時傳回非零結束碼。重跑同一命令時,會略過選定路徑下已是本機版本的伺服器。

--sudo 在標準輸入與標準錯誤都連接終端時,透過原生 SSH 終端輸入普通 sudo 密碼。非互動環境與 --json 模式使用 sudo -n,缺少免密權限時明確報錯。SSH 登入仍使用設定的金鑰與批次模式。

Serve 協定優勢

傳統 SSHServe 協定
連線建立每個檔案一個程序單一持久連線
檔案列表ssh find(shell 解析)二進位 LIST 訊息
雜湊校驗需傳回資料到本機伺服端直接計算 BLAKE3
上傳校驗需重新下載校驗伺服端回傳寫入後的雜湊
單檔開銷~50ms(程序啟動)~0.1ms(訊息幀)

校驗遠端傳輸

# 上傳並校驗完整性
bcmr copy -V local_file.txt user@host:/backup/

原子上傳與覆蓋策略

Serve PUT 預設不覆蓋已存在的目標。只有明確使用 --force --yes,用戶端才會在 v2 協定中攜帶覆蓋決定:

# 遠端已有 report.pdf 時失敗,並保留舊檔案
bcmr copy report.pdf user@host:/backup/

# 同步落盤後原子取代(要求協商 serve CAP_SYNC)
bcmr copy --force --yes --sync report.pdf user@host:/backup/

# 明確校驗完成後發布
bcmr copy --force --yes --verify report.pdf user@host:/backup/

伺服端先寫入私有、與控制代碼綁定的交易,校驗長度與雜湊後才發布。 中斷的強制覆蓋會保留舊的最終路徑;流水線目錄上傳對每個檔案都 維持同樣的屬性。

新的傳統 SSH 上傳同樣先寫私有暫存檔案。帶 -p 或 -V 的上傳會在 私有暫存路徑上完成屬性和校驗,再發布。輔助 SSH 命令無法提供可檢查的 目錄 fsync,因此傳統上傳、保留連結的上傳,以及同時帶 -p 或 -V 的 上傳使用 --sync 時,都會在寫入目標之前明確報錯。普通 serve 上傳要求 所有連線都協商 CAP_SYNC,缺少該能力時不會靜默降級。Unix 同步下載會 同步本機發布操作。

Copy 預設跟隨連結;--no-deref 保留連結物件,包括斷鏈。Move 始終保留 連結物件。這條遠端路徑使用 SSH 輔助命令,不支援 --direct direct; dry-run 仍可預覽。

正式版暫時停用單檔跨連線分片 PUT,因為獨立連線還無法安全加入 同一個伺服端交易。-P N 仍會並行處理遞迴批次中的不同檔案。

內容定址去重(CAP_DEDUP)

serve 協定內建區塊級去重:≥ 16 MiB 的 PUT 會先交換每個 4 MiB 區塊的 BLAKE3 雜湊,伺服端只索取那些不在本機內容定址儲存(CAS)裡的區塊。CAS 路徑由 BCMR_CAS_DIR / BCMR_CAS_CAP_MB 控制。

從 0.7.1 起,Linux/macOS serve 快取採用私有權限,並依固定的根目錄身分隔離;不同根目錄不能重用彼此的區塊。所有 serve 根目錄共用一個容量上限,本機 CAS 維持獨立快取。升級後的首次上傳會重新填入隔離快取。FreeBSD、Windows 等其他平台伺服端會索取全部資料區塊,暫不快取去重區塊。快取目錄無法使用或不安全時,停用這項加速,普通傳輸繼續。

對每個夠大的檔案 PUT 自動生效 — 無需額外旗標啟用。收益在「同一個建置產物反覆上傳」(開發迴圈)這種場景最明顯:第二次上傳略過伺服端已經有的所有區塊。

# 第一次:整個 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 連線;設定 BCMR_SSH_NO_MULTIPLEX=1 可停用
  • Serve 工作階段池:明確停用 ControlMaster,使並行成員使用互相獨立的 TCP/加密串流
  • 每 15 秒探測無流量的 SSH 工作階段,連續 20 次無回應後關閉;持續有流量的慢速連線不會被誤判
  • 同步下載會先一次解析最深的既存目錄前綴;指向有效目錄的 symlink home/儲存前綴可用,斷裂 symlink 會在建立任何含糊目標前報錯
  • 透過 SSH 串流傳輸資料並追蹤進度
  • 支援上傳和下載兩個方向

路徑偵測

BCMR 透過 [user@]host:path 格式偵測遠端路徑。以下模式被識別為本機路徑,不會觸發遠端模式:

  • 絕對路徑(/path/to/file)
  • 相對路徑(./file、../file)
  • 主目錄(~/file)
  • Windows 磁碟機代號(C:\file)