拷貝成萬上萬個小文件時,cp -r 因頻繁元數據操作 (inode 分配、目錄項更新、日誌寫入) 導致性能極差。本文提供四大加速方案:tar 管道流式傳輸、rsync 增量同步、cp 參數微調、並行化腳本,並對比本地/遠程場景適用性。
核心原理:tar 將文件流式打包輸出到 stdout,經管道直接輸入目標端 tar 解包,全程內存/網絡傳輸,無中間壓縮文件落盤,元數據操作合併為順序流。
# 源目錄 → 目標目錄 (保留權限、時間戳、擁有者、軟鏈接)
cd /src_dir
tar cf - . | (cd /dst_dir && tar xpf -)
# 參數詳解:
# c 创建, f - 文件名為 stdout/stdin
# p 保留權限 (默認 root 才生效), x 提取
# -C 目標目錄 可替換 subshell cd
tar cf - . | tar xpf - -C /dst_dir
# 方案 A: ssh 加密傳輸 (通用,穿透防火墻)
tar cf - /src_dir | ssh user@remote "tar xpf - -C /dst_dir"
# 方案 B: nc 裸流傳輸 (極速,需內網/信任環境,目標先監聽)
# 目標端:
nc -l -p 5555 | tar xpf - -C /dst_dir
# 源端:
tar cf - /src_dir | nc target_ip 5555
# 方案 C: ssh + 壓縮 (帶寬受限場景)
tar czf - /src_dir | ssh user@remote "tar xzf - -C /dst_dir" # z: gzip
tar cJf - /src_dir | ssh user@remote "tar xJf - -C /dst_dir" # J: xz (壓縮比高、慢)
# 本地/遠程通用,保留所有屬性 (-a = -rlptgoD)
rsync -avzP /src_dir/ user@remote:/dst_dir/
# 關鍵參數:
# -a 归档模式 (遞歸、保留鏈接/權限/時間/擁有者/設備/特殊文件)
# -v 详细输出
# -z 压缩传输 (網絡傳輸開啟,本地可省略)
# -P = --partial --progress (顯示進度、保留斷點文件可續傳)
# --delete 目標端刪除源端不存在的文件 (鏡像同步慎用)
# --exclude='*.tmp' 排除模式
# -e 'ssh -p 2222' 指定 SSH 端口
優勢:僅傳輸差異塊 (rolling checksum),斷點續傳,帶寬限流 (--bwlimit=10000 KB/s),保留硬鏈接/ACL/xattrs (-H -A -X)。
# 保留所有屬性 (等同 -dR --preserve=all)
cp -a /src_dir /dst_dir
# 显式指定保留屬性 (不跟隨軟鏈接 -d, 遞歸 -R)
cp -dR --preserve=mode,ownership,timestamps,context,links,xattr /src_dir /dst_dir
# 避免提示覆蓋
cp -f /src_dir/* /dst_dir/ # 強制覆蓋
# 或
yes | cp -r /src_dir /dst_dir
實測結論:本地極大量小文件,tar 管道 ≈ rsync -a > cp -a。但 cp 兼容性最好,無依賴。
單線程工具無法滿載多核 IO。GNU Parallel 或 xargs 並行:
# 方案 A: find + xargs -P (並行進程數)
find /src_dir -type f -print0 | xargs -0 -P 8 -I {} cp -p {} /dst_dir/{}
# 方案 B: GNU Parallel (功能更強)
parallel -j 8 cp -p {} /dst_dir/{} ::: /src_dir/*
# 方案 C: 簡單 Bash 循環 (適合文件名無特殊字符)
for f in /src_dir/*; do cp -p "$f" /dst_dir/ & done; wait
注意:並行度過高導致磁盤隨機 IO 暴增、元數據鎖爭用反而降速。機械盤建議 2-4,SSD/NVMe 可嘗試 8-16,iostat -x 1 觀察 %util 與 await。
| 場景 | 首選方案 | 備選 | 核心理由 |
|---|---|---|---|
| 本地海量小文件全量複製 | tar 管道 | rsync -a | 順序流元數據操作,最低延遲 |
| 遠程同步/增量備份/斷點續傳 | rsync -avzP | tar|ssh | 增量校驗、斷點續傳、帶寬控制 |
| 異構文件系統/跨平台 | rsync | tar|ssh | rsync 協議屏蔽底層差異 |
| 無 rsync/ssh 環境 (極简容器/嵌入式) | tar|nc | cp -a | 零依賴,裸流極速 |
| 需嚴格保留 ACL/xattr/硬鏈接 | rsync -aHAX | tar (需新版支持) | rsync 元數據保留最完整 |
# pv (Pipe Viewer) 可視化管道吞吐
tar cf - /src | pv | tar xpf - -C /dst
# 或
rsync -avzP --info=progress2 /src/ /dst/
# 校驗完整性 (源/目標生成清單對比)
find /src -type f -exec sha256sum {} + | sort > src.sha256
find /dst -type f -exec sha256sum {} + | sort > dst.sha256
diff src.sha256 dst.sha256
大量小文件拷貝的本質是 元數據操作風暴。tar 管道 通過流式封裝將隨機 IO 轉為順序流;rsync 通過增量校驗避免重複傳輸;並行化 利用多核隱藏延遲。根據「本地/遠程、全量/增量、一次性/常態化」選型,並用 pv/sha256sum 守護數據完整性。
