远程拷贝大文件,使用 scp 和 rsync 的优劣势比较
scp vs rsync 远程传输大文件 优劣对比
核心原理先理清
- scp:基于 SSH 协议,完整读取源文件 → 整体传输;没有增量机制(传统 OpenSSH scp,不支持断点续传、差异同步)
- rsync:默认也可走 SSH(rsync-over-ssh),核心是增量传输算法:先比对文件元信息+校验块,只传输文件变化部分
⚠️ 重要区分:现代 OpenSSH 新版虽然淘汰旧 scp 后端改用 sftp,但依然没有增量同步能力。
一、关键维度对比(大文件场景重点看)
| 对比项 | scp | rsync(ssh 通道) |
|---|---|---|
| 增量/断点续传 | ❌ 无。中断后只能从头重传;不能只传变更部分 | ✅ 支持。中断重跑只传缺失/变更块;文件局部修改仅传输差异数据 |
| 传输效率(全新文件) | 两者差距不大,底层都是SSH加密吞吐,瓶颈多在网络/磁盘 | 全新文件略多一步校验比对开销,轻微损耗;网络很差时影响可忽略 |
| 传输效率(已存在部分文件) | ❌ 全部重传,极度浪费带宽 | ✅ 巨大优势,只同步差异,带宽节省明显 |
| 文件属性保留 | 基础权限,复杂场景不稳定 | ✅ 完善:权限、属主、时间、软硬链接、设备文件等(-a) |
| 目录递归 | 支持,写法简单 | 支持,功能更强,可过滤文件(exclude/include) |
| 压缩传输 |
-C 开启SSH压缩,全局压缩数据流 |
--compress(rsync侧压缩,只压缩文件数据,更智能;区分文件类型) |
| 删除冗余文件 | 不支持同步删除目标多余文件 |
--delete 可同步清理目标端多余文件 |
| 限速 | 支持 -l
|
支持 --bwlimit,控制更精准 |
| 校验完整性 | 传输完成无内置校验,需额外md5sum | 内置校验选项 --checksum,可强制按文件哈希比对,防止静默损坏 |
| 依赖 | 几乎所有Linux默认预装 | 绝大多数系统自带;极精简嵌入式可能缺失rsync |
| 简单易用性 | 语法直观,新手友好 | 参数较多,需要熟悉常用参数 |
| 加密通道 | 原生SSH | 借助 rsync -e ssh 复用SSH加密,安全等级一致 |
二、优势详细拆解
✅ scp 优势
-
上手最简单
scp local.file user@ip:/path/ scp -r dir user@ip:/path/ -
依赖最低
只要能ssh登录,基本就有scp;嵌入式、极简服务器不容易缺失。 - 一次性完整拷贝小量文件,心智负担低
❌ scp 致命劣势(大文件场景痛点)
-
传输中断必须从头重来
几十GB/TB级文件,网络波动断开 = 前功尽弃。 -
无法利用目标已有同名文件
哪怕目标已经有99%相同文件,依然全部重传。 - 文件元数据同步能力弱,备份场景不友好。
✅ rsync 优势(大文件/批量文件首选)
-
增量同步 + 可中断续传(最重要)
超大文件、不稳定网络下碾压scp。 -
丰富的备份特性
保留权限、时间戳、软链接,支持清理多余文件、过滤不需要传输的文件。 -
可控性强:限速、dry-run试运行(
--dry-run),先预览再传输,避免误删。 - 灵活压缩策略,比scp全局压缩更高效
❌ rsync 劣势
-
两端都需要安装 rsync 程序
远端服务器如果没有rsync,则无法使用rsync协议传输。 - 参数较多,新手容易写错(比如忘记
-a导致属性丢失) - 全新未存在文件时,多一轮文件比对开销,本地高速内网、极小文件场景略微慢一点(带宽充足时感知不强)
三、推荐使用场景
👉 选择 scp
- 临时拷贝少量、不大的文件,一次性传输,网络稳定;
- 远端服务器没有安装rsync,且无法安装;
- 不想记忆复杂参数,追求最简命令。
👉 强烈推荐 rsync(大文件首选)
- 文件体积大(几十GB+)、网络不稳定,担心断连重传;
- 需要定期同步、增量备份(日志、虚拟机镜像、素材库);
- 需要保留文件权限、时间,同步目录、清理多余文件;
- 文件可能局部修改,只希望传输改动部分。
四、常用参考命令模板
scp 示例
# 带压缩
scp -C bigfile.iso root@192.168.10.10:/data/
rsync 常用模板(ssh通道,生产常用)
# -a 归档模式;-v显示过程;-z传输压缩;--progress进度
rsync -avz --progress bigfile.iso root@192.168.10.10:/data/
# 目录同步 + 删除目标多余文件(谨慎使用--delete,先加--dry-run预览)
rsync -avz --progress --delete --dry-run /local/dir/ root@ip:/remote/dir/
五、补充重要误区澄清
-
rsync 续传 ≠ 断点续下载
rsync先比对文件块;如果目标文件是残缺文件,会对比相同块复用,不是简单从字节位置续传,但效果对大文件非常友好。 - 内网万兆高速、极小文件场景:两者差距很小;瓶颈通常是磁盘IO而非传输协议。
- 如果两端不能装rsync,又需要断点续传:可以组合
split分片 + scp,或者使用curlftpfs、rclone 等工具作为替代方案。
如果你需要,我可以给一份超大文件远程传输最优实践方案(含带宽优化、防中断脚本、校验手段)。
目标机器如果有密码,如果在脚本中传递使用?
$ rsync -avP root@xx.xx.xx.xx:/sourPath/file /localPath/
$ rsync -avP /localPath/file root@xx.xx.xx.xx:/sourPath/
先说核心结论
rsync + ssh 默认不支持命令行直接传密码(ssh 出于安全设计禁止 -password 参数),脚本里有三种主流方案,按推荐优先级排序:
方案1:SSH免密登录(✅生产首选,强烈推荐)
原理:把本机公钥放到远端 root@xx.xx.xx.xx 的 ~/.ssh/authorized_keys,不需要输入密码。
操作
# 本机执行,一路回车生成密钥(已有可跳过)
ssh-keygen
# 推送公钥到远端
ssh-copy-id root@xx.xx.xx.xx
之后你的脚本命令直接原样运行,无需密码:
rsync -avP root@xx.xx.xx.xx:/sourPath/file /localPath/
优点:安全、稳定、无额外依赖;
缺点:需要一次手动配置;服务器禁止密钥登录时无法使用。
方案2:使用 sshpass(脚本临时自动填密码,适合无法配置免密场景)
⚠️ 风险:密码明文写在脚本里,有安全隐患,仅限内网测试环境,不要用于公网生产环境!
1)先安装 sshpass
# CentOS/RHEL
yum install sshpass -y
# Debian/Ubuntu
apt install sshpass -y
2)脚本写法
# 定义密码
PASSWORD="你的远程root密码"
REMOTE_IP="xx.xx.xx.xx"
sshpass -p "$PASSWORD" rsync -avP \
-e "ssh -o StrictHostKeyChecking=no" \
root@$REMOTE_IP:/sourPath/file /localPath/
参数说明:
-
-e "ssh xxx":指定rsync使用的ssh命令 -
-o StrictHostKeyChecking=no:自动接受主机指纹,避免脚本卡住
进阶:不要直接明文写密码,可以把密码存入权限严格保护的文件:
# 密码文件 chmod 600 pass.txt
sshpass -f pass.txt rsync -avP -e "ssh -o StrictHostKeyChecking=no" root@xx.xx.xx.xx:/sourPath/file /localPath/
⚠️ sshpass 重大风险提醒
- 通过
ps命令可能短暂看到明文密码; - 脚本文件如果权限不严格,其他人能读取密码;
- 很多安全基线、堡垒机环境禁止 sshpass。
方案3:expect 模拟交互式输入(备选,不推荐优先用)
如果服务器无法安装 sshpass,可以用 expect 模拟人工输入密码,代码示例:
#!/bin/bash
REMOTE_PWD="你的密码"
REMOTE_IP="xx.xx.xx.xx"
expect -c "
spawn rsync -avP root@$REMOTE_IP:/sourPath/file /localPath/
expect \"root@$REMOTE_IP's password:\"
send \"$REMOTE_PWD\r\"
interact
"
缺点:代码繁琐、容易受中英文提示、超时影响,稳定性不如 sshpass。
重要避坑点
- ❌ rsync 没有
--password参数接收ssh登录密码;网上很多错误说法。 - 如果是 rsync daemon 模式(rsync://) 才有
--password-file,不是ssh通道,不要混淆!- 你现在命令格式:
user@ip:/path→ rsync over ssh,走ssh认证; -
rsync://user@ip/module→ rsync daemon协议,两套认证完全不一样。
- 你现在命令格式:
区分两种模式(防止踩坑)
你当前方式(ssh通道,绝大多数场景)
rsync root@ip:/remote/path localpath
# 认证依靠ssh,只能用免密 / sshpass / expect
rsync daemon模式(独立rsync服务,极少使用)
rsync rsync://root@ip/module/file localpath
# 这种才支持 --password-file
最终建议
- 正式环境、长期定时同步:优先 SSH 免密(方案1)
- 临时脚本、内网一次性任务、无法配置密钥:sshpass(方案2)
- 公网环境禁止把明文密码写进脚本!
如果你需要,我可以给一份完整可直接运行的shell脚本(包含日志输出、失败判断)。