返回首页

scp 与 rsync:服务器文件传输工具用法与优劣解析

📅 创建于 2026-06-01 🔄 更新于 2026-06-01 📝 1642 字

scp 与 rsync:服务器文件传输工具用法与优劣解析

来源:马哥Linux运维 | 发布日期:2026-05-29

在服务器运维中,经常需要在本机和远程服务器之间、或两台服务器之间传输文件。scp 语法简单适合小文件一次性传输,rsync 支持增量同步和断点续传适合大文件迁移和定期备份。本文面向初中级运维工程师,详细讲解两个工具的用法、参数、实战场景和常见问题解决方案。


一、scp 详解

基本原理

scp(Secure Copy)基于 SSH 协议实现文件加密传输。在本地执行命令,通过 SSH 连接到远程主机完成传输后返回结果。

  • 优点: 简单易用,一行命令搞定
  • 缺点: 每次传输复制全部文件,不支持增量同步

基本语法

# 从本地复制到远程
scp [选项] 源路径 目标路径

# 从远程复制到本地
scp [选项] 远程用户@远程主机:远程路径 本地路径

# 从远程复制到远程(不经过本地中转)
scp [选项] 用户1@主机1:路径1 用户2@主机2:路径2

常用参数

参数 作用 示例
-r 递归复制整个目录 scp -r /dir user@host:/dest/
-p 保留原文件的修改时间、访问时间和权限 scp -p file user@host:/dest/
-q 静默模式,不显示传输进度 scp -q file user@host:/dest/
-v 详细/调试模式,显示 SSH 连接过程 scp -v file user@host:/dest/
-C 启用压缩传输 scp -C file user@host:/dest/
-P port 指定 SSH 端口(注意是大写 P scp -P 2222 file user@host:/dest/
-i file 指定私钥文件 scp -i ~/.ssh/id_rsa file user@host:/dest/
-l limit 限制带宽(单位 Kbit/s) scp -l 4000 file user@host:/dest/
-o option 传递 SSH 选项 scp -o "ConnectTimeout=10" file user@host:/dest/
-F file 指定 SSH 配置文件 scp -F ~/.ssh/prod_config file user@host:/dest/

实战场景

场景一:本地上传到远程

# 上传单个文件
scp /path/to/local/file.txt [email protected]:/remote/path/

# 指定 SSH 端口(非默认 22)
scp -P 2222 /path/to/local/file.txt [email protected]:/remote/path/

# 指定私钥
scp -i ~/.ssh/id_rsa /path/to/local/file.txt [email protected]:/remote/path/

# 保留文件属性
scp -p /path/to/local/file.txt [email protected]:/remote/path/

场景二:远程下载到本地

# 下载单个文件
scp [email protected]:/remote/path/file.txt /local/path/

# 下载整个目录
scp -r [email protected]:/remote/path/directory /local/path/

场景三:两台远程服务器直传

不经过本地中转,直接在两台服务器之间传输:

scp user1@host1:/path/to/file user2@host2:/path/to/destination/

这样传输速度是两台远程服务器之间的直连速度,不受本地带宽影响。

场景四:批量上传多个文件

# 使用通配符
scp /local/path/*.txt [email protected]:/remote/path/

# 空格分隔多个文件
scp file1.txt file2.txt file3.txt [email protected]:/remote/path/

场景五:限制带宽传输

大文件传输时避免占满业务带宽:

# 限制带宽为 500KB/s
scp -l 4000 /largefile.tar.gz [email protected]:/remote/path/

注意: -l 参数的单位是 Kbit/s,不是 KB/s。限制 500KB/s 需要设置 -l 4000(500 × 8 = 4000)。

场景六:压缩传输

压缩可以减少传输数据量,对文本文件效果明显,对已压缩文件(.tar.gz、.zip)效果有限:

scp -C /path/to/largefile.tar.gz [email protected]:/remote/path/

实战技巧

使用 SSH Config 简化连接

~/.ssh/config 中添加主机配置,之后可以直接用别名传输:

# ~/.ssh/config
Host prod-server
    HostName 192.168.1.100
    User remote_user
    Port 22
    IdentityFile ~/.ssh/id_rsa

Host prod-backup
    HostName 192.168.1.101
    User backup_user
    Port 2222

之后可以直接用:

scp file.txt prod-server:/remote/path/
scp prod-server:/remote/file.txt prod-backup:/backup/

传输后验证

# 对比文件大小
ssh user@host "ls -lh /remote/path/file.txt"
ls -lh /local/path/file.txt

# 对比 MD5
md5sum /local/file.txt
ssh user@host "md5sum /remote/file.txt"

二、rsync 详解

基本原理

rsync 的核心优势是增量同步。通过特殊的校验算法,只传输源文件和目标文件之间不同的部分,大大减少网络传输量和同步时间。

支持三种工作模式:

  • 本地同步: 在同一个机器上同步目录
  • 远程 Shell 同步: 通过 SSH 通道传输(最常用)
  • rsync 守护进程同步: 通过 rsync daemon 服务(适合大规模部署)

基本语法

# 本地同步
rsync [选项] 源路径 目标路径

# 远程同步(通过 SSH,最常用)
rsync [选项] 源路径 用户@主机:目标路径

# 从远程同步到本地
rsync [选项] 用户@主机:源路径 本地目标

# 远程同步(通过 rsync daemon)
rsync [选项] 源路径 用户@主机::模块/目标路径

常用参数

参数 作用 说明
-a 归档模式 等价于 -rlptgoD,保留权限/时间/属主/属组/符号链接/设备文件,推荐使用
-v 显示传输详情 显示传输的文件列表和统计信息
-z 压缩传输 传输时压缩,减少网络流量
-r 递归同步 但不保留权限和时间戳,建议用 -a 替代
-P 进度 + 断点续传 等价于 --partial --progress大文件推荐
--delete 删除多余文件 目标端删除源端不存在的文件,双向完全一致
--exclude=PATTERN 排除匹配文件 支持多个 --exclude,也支持 --exclude-from=file
--bwlimit=RATE 限制带宽 单位 KB/s,和 scp 不同(rsync 用 KB/s,scp 用 Kbit/s)
-n / --dry-run 模拟运行 显示将要传输的文件,不实际执行
--remove-source-files 传输后删除源文件 类似 mv,慎用
-u / --update 仅更新较新文件 跳过目标端较新的文件
--link-dest=DIR 硬链接增量备份 相同文件做硬链接,极省空间
--partial 保留部分传输文件 配合 -P 使用

实战场景

场景一:本地目录同步

# 归档模式递归同步
rsync -av /source/dir/ /backup/dir/

关于尾部斜杠的要点:

  • 加斜杠(/source/dir/):同步目录内容到目标
  • 不加斜杠(/source/dir):连目录本身一起同步
# 示例对比
rsync -av /data/app/ /backup/app/    # 结果:/backup/app/ 下面直接是文件
rsync -av /data/app /backup/          # 结果:/backup/app/ 下面才是文件

场景二:远程同步到本地

# 通过 SSH 远程同步到本地
rsync -avz user@host:/remote/dir/ /local/dir/

# 指定 SSH 端口(使用 -e 参数)
rsync -avz -e "ssh -p 2222" user@host:/remote/dir/ /local/dir/

场景三:本地同步到远程并删除多余文件

# 备份场景,确保目标端和源端完全一致
rsync -avz --delete /local/dir/ user@host:/backup/dir/

特别适合: 定期备份、镜像同步、灾备切换。

场景四:排除特定文件和目录

# 排除单个模式
rsync -av --exclude='*.log' /src/ /dest/

# 排除多个模式
rsync -av --exclude='*.log' --exclude='cache/' --exclude='tmp/' /src/ /dest/

# 从文件中读取排除规则
rsync -av --exclude-from=exclude.txt /src/ /dest/

exclude.txt 格式示例:

*.log
*.tmp
cache/
node_modules/
.git/
.env

场景五:模拟运行(先看效果再执行)

# 只显示将要传输的文件,不实际执行
rsync -av --dry-run /src/ /dest/

强烈建议: 重要操作之前先用 -n 预览结果。

场景六:断点续传

# -P 等价于 --partial --progress
rsync -avP /largefile.tar.gz user@host:/dest/

传输中断后,重新执行同样的命令即可继续——rsync 会自动识别已传输的部分。

增量同步演示

# 模拟:第一次全部传输
echo "data1" > /tmp/testdata.ext
rsync -avh /tmp/testdata.ext /tmp/backup/
# 输出:sending incremental file list → testdata.ext(第一次,全量)

# 模拟:追加数据后第二次传输
echo "data2" >> /tmp/testdata.ext
rsync -avh /tmp/testdata.ext /tmp/backup/
# 输出:sending incremental file list → testdata.ext(第二次,只传变化部分)

原理: rsync 使用 rolling checksum 算法,将文件切分为固定大小的块(block),逐块校验对比,只传输发生变化的块。


三、scp vs rsync 详细对比

核心差异

对比维度 scp rsync
传输方式 全部传输 增量传输(只传变化部分)
断点续传 ❌ 不支持 -P / --partial
第一次速度 较快(无校验开销) 较快(算法开销小)
后续速度 慢(每次都全量) 快很多(增量)
压缩传输 -C -z
带宽限制 -l(Kbit/s) --bwlimit(KB/s)
排除文件 ❌ 不支持 --exclude
删除同步 ❌ 不支持 --delete
预览模式 ❌ 不支持 -n / --dry-run
保留文件属性 -p -a(更全面)
语法复杂度 ⭐ 简单 ⭐⭐ 中等
适用场景 小文件、临时传输 大文件、定期同步、备份

性能对比案例

假设源目录有 1000 个文件,其中只有 10 个发生了变化:

场景 scp rsync
1000 个文件,10 个变化 传输全部 1000 个 只传 10 个
10GB 文件,修改了 200MB 传输整个 10GB 只传 200MB
日常定时同步 每次都全量,浪费带宽 增量同步,高效执行

选择指南

场景 推荐工具 原因
临时拷贝一两个小文件 scp 语法简单,一行命令搞定
大文件(>500MB)传输 rsync 支持断点续传,不怕中断
定期备份/同步 rsync 增量同步,配合 cron 高效执行
大量小文件 rsync 先 tar 打包再同步,避免逐个文件握手开销
两台远程服务器间传输 scp 直接直传,无需本地中转
需要排除某些文件 rsync scp 不支持 exclude

四、实战案例

案例一:日志迁移

需求: 将历史日志文件从生产服务器迁移到备份服务器,控制带宽占用。

#!/bin/bash
# migrate_logs.sh - 日志迁移脚本
SOURCE_USER=root
SOURCE_HOST=192.168.1.100
SOURCE_DIR="/var/log/myapp/archive/"
TARGET_DIR="/backup/logs/myapp/"

# 第一步:先 rsync 同步大部分数据(白天执行,限制带宽)
rsync -avz --bwlimit=5120 \
  $SOURCE_USER@$SOURCE_HOST:$SOURCE_DIR \
  $TARGET_DIR

# 第二步:业务低峰期(凌晨)做最终增量同步
# (配合 cron 在凌晨 2 点执行)
# rsync -avz $SOURCE_USER@$SOURCE_HOST:$SOURCE_DIR $TARGET_DIR

# 第三步:迁移完成后验证
echo "=== 文件数量对比 ==="
echo "源端:$(ssh $SOURCE_USER@$SOURCE_HOST "find $SOURCE_DIR -type f | wc -l")"
echo "目标:$(find $TARGET_DIR -type f | wc -l)"

echo "=== MD5 抽样校验 ==="
for f in $(ssh $SOURCE_USER@$SOURCE_HOST "ls $SOURCE_DIR | head -5"); do
  echo "源端 $f: $(ssh $SOURCE_USER@$SOURCE_HOST "md5sum $SOURCE_DIR$f" | cut -d' ' -f1)"
  echo "目标 $f: $(md5sum $TARGET_DIR$f | cut -d' ' -f1)"
done

案例二:零停机代码部署

需求: 使用 rsync 实现零停机代码部署,先同步到测试目录验证,确认无误后切换。

#!/bin/bash
# deploy.sh - 零停机部署脚本
APP_NAME="myapp"
SOURCE_DIR="/data/build/$APP_NAME/"
TEST_DIR="/data/$APP_NAME-test/"
PROD_DIR="/data/$APP_NAME/"

# 1. 同步到测试目录
echo ">>> 同步到测试目录..."
rsync -avz --delete $SOURCE_DIR $TEST_DIR

# 2. 在测试目录执行验证
echo ">>> 执行部署前验证..."
cd $TEST_DIR
# ./run_checks.sh  # 自定义验证脚本

# 3. 确认无误后,同步到正式目录
echo ">>> 切换到正式目录..."
rsync -avz --delete $TEST_DIR $PROD_DIR

# 4. 重启服务(按需)
# systemctl restart $APP_NAME

echo ">>> 部署完成"

五、安全注意事项

# 1. SSH 密钥认证(推荐,替代密码)
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519
ssh-copy-id user@host

# 2. 使用非默认 SSH 端口(降低被扫描风险)
# 服务端 /etc/ssh/sshd_config: Port 22222
# 客户端连接: scp/rsync -e "ssh -p 22222"

# 3. 限制可执行命令
# 在远程用户 ~/.ssh/authorized_keys 中限制:
# command="/usr/bin/rsync --server ..." ssh-ed25519 AAA...

# 4. 排除敏感文件
# .env、*.key、*.pem 等不要传输到不信任的服务器

# 5. 传输日志记录
rsync -av --log-file=/var/log/rsync.log /src/ user@host:/dest/

六、常见问题

1. Connection refused

# 检查远程 SSH 是否运行
ssh -v user@host

# 检查端口
nc -zv host 22
telnet host 22

2. Permission denied

# 检查目标目录写权限
ssh user@host "ls -ld /target/dir"

# 检查密钥权限
chmod 600 ~/.ssh/id_rsa
chmod 700 ~/.ssh

# 检查 authorized_keys
ssh user@host "cat ~/.ssh/authorized_keys | grep your-key"

3. 传输速度慢

# 确认用了压缩
scp -C file user@host:/dest/
rsync -avz file user@host:/dest/

# 检查带宽限制
# scp -l 值可能设太小

# 网络质量排查
mtr host
ping -c 100 host

# 大量小文件时先打包
tar czf - /data/files/ | ssh user@host "tar xzf - -C /dest/"

4. 断点续传

scp 不支持断点续传。传输中断后需要重新传输整个文件。 rsync 天然支持,传输中断后重新执行即可:

rsync -avP /largefile.tar.gz user@host:/dest/

七、传输前中后检查清单

传输前检查

[ ] 确认源文件路径正确
[ ] 确认目标路径存在或有写权限
[ ] 确认 SSH 连接正常(ssh 连接测试)
[ ] 确认目标服务器磁盘空间充足(df -h)
[ ] 确认网络带宽不会影响业务
[ ] 确认传输时间窗口(业务低峰期首选)

传输后验证

# 对比文件数量
echo "源端:$(ssh user@host "find /remote/dir -type f | wc -l")"
echo "目标:$(find /local/dir -type f | wc -l")"

# 对比文件大小
du -sh /local/dir
ssh user@host "du -sh /remote/dir"

# 抽样校验 MD5
for f in file1 file2 file3; do
  echo "源端: $(md5sum /local/dir/$f | cut -d' ' -f1)"
  echo "目标: $(ssh user@host "md5sum /remote/dir/$f | cut -d' ' -f1")"
done

自动化巡检脚本

配合 cron 实现定期同步检查:

#!/bin/bash
# /etc/cron.daily/check_sync.sh
LOG_FILE="/var/log/sync_check.log"
SOURCE="user@host:/data/"
TARGET="/backup/data/"
DATE=$(date '+%Y-%m-%d %H:%M:%S')

echo "[$DATE] 开始同步检查..." >> $LOG_FILE

# 用 --dry-run 模拟同步,统计需要传输的文件数
CHANGES=$(rsync -avzn --delete $SOURCE $TARGET | wc -l)

if [ $CHANGES -gt 3 ]; then  # 减去输出的统计行
  echo "⚠️  发现 $CHANGES 个文件需要同步,执行增量同步..."
  rsync -avz --delete $SOURCE $TARGET >> $LOG_FILE 2>&1
  echo "✅ 同步完成" >> $LOG_FILE
else
  echo "✅ 两端一致,无需同步" >> $LOG_FILE
fi

八、快速参考

日常场景对照

你要做什么 命令
上传文件到远程 scp file user@host:/dest/rsync -avz file user@host:/dest/
从远程下载文件 scp user@host:/file .rsync -avz user@host:/file .
同步整个目录 rsync -avz /src/ user@host:/dest/
增量同步(仅更新变化) rsync -avz /src/ user@host:/dest/
排除 log 文件同步 rsync -avz --exclude='*.log' /src/ user@host:/dest/
断点续传大文件 rsync -avP /bigfile user@host:/dest/
限制带宽传输 scp -l 4000 file user@host:/dest/
模拟运行看效果 rsync -avz --dry-run /src/ user@host:/dest/
远程服务器间直传 scp user1@h1:/file user2@h2:/dest/
压缩传输加速 scp -C file user@host:/dest/rsync -avz file user@host:/dest/

最佳实践总结

  1. SSH 密钥认证 — 避免每次输入密码,安全又方便
  2. 重要操作先 dry-runrsync -n 预览变更,避免误操作
  3. 设置带宽限制 — 大文件传输时使用 --bwlimit-l,不影响业务
  4. 排除敏感文件.env*.key*.pem 不传不该传的地方
  5. 记录传输日志rsync --log-file= 便于排查和审计
  6. 验证传输结果 — 文件数量/大小/MD5 三确认
  7. 大量小文件先打包tar czf - | ssh tar xzf - 避免逐个文件握手开销
  8. 调度在业务低峰期 — 配合 cron 定时执行

关联页面

页面关联点
linux-essential-commands-referenceLinux 常用命令手册
linux-compression-tools-comparison压缩解压工具对比(tar/gzip/zip)
linux-filesystem-directory-structure-guideLinux 文件系统目录结构
linux-awk-sed-text-processingawk 与 sed 批量文本处理实战:字段分析/日志统计/配置批量修改/脚本自动化,8大Nginx日
linux-file-transfer-guideLinux 大文件传输方案选型:五大方案(rsync/scp/nc+tar/split/aria2)
ops-automation-scripts运维自动化脚本(文件传输在自动化中的典型位置)