
在Linux系统中cp 命令只擅长做一件事:复制文件,但它不提供进度指示、不限制速率、不支持断点续传,也没有内置的校验和验证功能。
在本地复制几兆字节的数据时,这没什么问题。但当我们需要通过网络链路传输 40GB 的数据库转储,或者将 20 万个零散小文件复制到新磁盘时,我们需要的绝不仅仅是一个闪烁的光标和默默的祈祷。
如果经常在服务器之间迁移大型数据集,那么下面列举的工具可以试试:
rsync:断点续传文件传输的首选工具当 cp 不够用时,rsync 是第一个值得考虑的工具。因为它只复制源与目标之间的差异部分,支持断点续传,并且既可用于本地复制,也可通过 SSH 进行远程传输。
如果系统中尚未安装,可以用以下命令安装:
sudo apt install rsync # Debian, Ubuntu, Mint
sudo dnf install rsync # RHEL/CentOS/Fedora, Rocky/AlmaLinux
一个标准的本地目录复制命令如下:
rsync -av --progress /source/directory/ /destination/directory/
输出示例:
sending incremental file list
database/
database/dump_2024.sql
2,147,483,648 100% 98.45MB/s 0:00:20 (xfr#1, to-chk=0/2)
sent 2,147,483,909 bytes received 35 bytes 102.24MB/s total size is 2,147,483,648
参数说明:
-a:启用归档模式,该选项一次性保留了权限、时间戳、符号链接及递归目录结构。-v:在传输过程中打印每个文件的名称。--progress:显示每个文件的实时传输速率和百分比进度。# 关于源路径末尾斜杠的说明:
/source/directory/ 末尾的斜杠很重要。带斜杠时,rsync 复制的是该目录下的内容;不带斜杠时,rsync 会将目录本身作为子目录复制到目标路径下。如果弄错了,可能会得到 /destination/directory/directory/ 这样的嵌套目录,而非预期结果。
要通过 SSH 复制到远程服务器,语法几乎相同:
rsync -av --progress /local/path/ user@remote-ip:/remote/path/
将 remote-ip 替换为服务器 IP 地址,可用 ip a 命令查看。
如果传输中途中断,只需再次运行相同的命令,rsync 会从断点处继续,自动跳过已成功传输的文件。
pv:为文件传输添加进度条pv(Pipe Viewer,管道查看器)是一个小巧的实用工具,它位于 Unix 管道之中,能够显示传输速度、已用时间和预估完成时间。它并不取代 cp 或 rsync,而是为它们提供“包装”。
安装命令:
sudo apt install pv # Debian, Ubuntu, Mint
sudo dnf install pv # RHEL/CentOS/Fedora, Rocky/AlmaLinux
最简单的用法是复制单个大文件并显示实时进度条:
pv /source/large-file.iso > /destination/large-file.iso
输出示例:
8.35GiB 0:01:22 [ 104MiB/s] [=========> ] 63% ETA 0:00:47
这个输出让你精确了解磁盘的实际写入速度,这是纯 cp 命令永远无法提供的。另外还可以将 pv 与压缩命令组合,一次性完成归档和复制:
pv /source/large-file.tar | gzip > /destination/large-file.tar.gz
管道分解:
(1)
pv /source/large-file.tar读取源文件并将吞吐量信息输出到终端。(2)
gzip实时压缩数据流。(3)
> /destination/large-file.tar.gz将压缩后的输出写入目标文件。
dd:用于磁盘克隆和原始复制的强大工具dd 是一个更底层的工具,已预装在每一个 Linux 系统上。它按原始块进行读写,因此非常适合克隆整个磁盘或分区、创建磁盘镜像以及测试原始磁盘吞吐量。
dd 的风险在于:输出路径的一个拼写错误可能在不经警告的情况下抹除错误磁盘的数据。因此,在运行之前,请务必反复确认目标设备是否正确。
一个典型的磁盘到磁盘克隆命令如下:
sudo dd if=/dev/sda of=/dev/sdb bs=64K conv=noerror,sync status=progress
输出示例:
50033664512 bytes (50 GB, 47 GiB) copied, 623.847 s, 80.2 MB/s
参数说明:
if=/dev/sda:指定输入文件,即源磁盘。of=/dev/sdb:指定输出文件,即目标磁盘。运行前请务必用 lsblk 确认这是正确的设备。bs=64K:设置块大小为 64KB。对于大块顺序读取,这比默认的 512 字节块大小要快得多。conv=noerror,sync:指示 dd 在遇到读取错误时继续执行,并用零填充坏块,而不是直接终止整个复制过程。status=progress:每隔几秒打印一次实时吞吐量。警告:
dd不会请求确认。如果把if和of写反了,会把源磁盘的数据写入目标磁盘,从而销毁你原本想要复制的数据。
parallel + rsync:更快复制数百万个小文件rsync 对于大文件来说速度很快,但每次传输是单线程的。当目录中有数十万个小文件时——比如 Node.js 的 node_modules 目录、邮件队列或照片库——rsync 的耗时可能远超预期,因为每个文件的开销(而非实际数据传输时间)占据了主导地位。
GNU Parallel 通过同时运行多个 rsync 任务来解决这个问题。
安装命令:
sudo apt install parallel # Debian, Ubuntu, Mint
sudo dnf install parallel # RHEL/CentOS/Fedora, Rocky/AlmaLinux
然后,在大型目录树上并行运行 rsync:
find /source/directory -mindepth 1 -maxdepth 1 -type d | \
parallel -j 4 rsync -a {} /destination/directory/
管道分解:
(1)
find /source/directory -mindepth 1 -maxdepth 1 -type d:列出源目录下的顶层子目录。(2)
parallel -j 4:同时运行 4 个rsync任务,每个子目录对应一个任务。根据你的 CPU 核心数和磁盘速度调整-j参数的值。(3)
rsync -a {} /destination/directory/:将每个子目录同步到目标路径,{}会被替换为具体的目录名。
在处理包含 50 万个小文件的目录时,这种方法通常能将复制时间缩短 **60% 到 70%**,相比单个 rsync 进程有明显提升,因为 I/O 队列始终保持满载,而不是逐个文件地等待。
如果复制完成后不验证数据是否完整无误,那么以上工具的意义都会大打折扣。对于任何关键数据的复制,请在传输完成后进行校验和比对。
SHA256 是大多数场景下的合适选择:
sha256sum /source/large-file.iso /destination/large-file.iso
输出示例:
a3b4c1d2e5f6... /source/large-file.iso
a3b4c1d2e5f6... /destination/large-file.iso
如果两个哈希值完全一致,说明复制结果是逐字节精确的。如果它们不一致,说明传输过程中出现了问题——例如磁盘错误、网络损坏,或有其他进程正在写入源文件,所以需要重新复制。
cp 适合把一个配置文件从一个目录移到另一个目录。但对于真正的系统管理工作——比如大型备份、远程同步、磁盘克隆以及包含数百万个 inode 的目录——我们必须使用更专业的工具:
rsync 提供断点续传和增量传输。pv 让传输过程可视化。dd 提供块级别的底层控制。parallel + rsync 在处理小文件密集的目录时大幅提升吞吐量。