scp适合单次、简单、不需历史记录的文件传输,如调试配置或拉取日志;rsync适用于重复同步、大文件、断点续传、权限保留及排除规则等场景。

选 rsync 还是 scp,不看文档,直接看场景:传一次小文件、临时调试用 scp;只要涉及重复同步、大文件、断网重试、保留权限或跳过某些内容,一律上 rsync。
scp 适合什么情况:简单、单次、不关心历史
它就是个“带 SSH 加密的 cp”,没逻辑判断,只管搬。比如:
- 把刚改好的
nginx.conf丢到测试机上试一下:scp -p nginx.conf user@192.168.1.20:/etc/nginx/ - 从生产机拉一个日志片段回本地分析:
scp user@prod:/var/log/app/error.log.20260415 . - 用密钥免密后,脚本里一行搞定,不用处理失败重试逻辑
注意:scp 不加 -p 就丢掉时间戳和权限;不加 -r 根本传不了目录;-P(大写)才是指定端口,写成小写就静默失败。
rsync 增量同步怎么生效:靠比对,不是靠“记得”
rsync 默认只看两个东西:文件大小 + 修改时间(mtime)。只要这两项一致,就跳过——哪怕内容其实变了。所以:
- 开发环境反复改代码再同步,
rsync -avz src/ user@host:/deploy/几乎秒完成 - 传一个 2GB 的数据库 dump,中间断了?再跑一遍,它自动从断点续传(前提是目标端已有部分文件)
- 想确保内容真一致,加
--checksum,但会慢——因为要读完整个文件算校验和
别指望它“记住上次传了哪些”。每次运行都是独立比对,所以首次同步可能略慢(扫描开销),后续才快。
排除文件或目录:scp 做不到,rsync 用 --exclude 很稳
scp 没有排除机制。想跳过 node_modules 或 *.log?只能先 tar 打包过滤,再传,麻烦且易错。
rsync 原生支持,规则清晰:
rsync -av --exclude='node_modules' --exclude='*.tmp' ./project/ user@host:/app/-
--exclude是模式匹配,不是路径通配;node_modules/开头的写法更安全(避免误杀文件名含node_modules的文件) - 远程排除也有效:
rsync -av --exclude='cache/' user@host:/var/www/ ./backup/
多个 --exclude 可叠加,顺序无关,但注意 shell 通配符会被本地提前展开,必要时用单引号包住。
权限、软链接、删除残留:rsync 的 -a 和 --delete 是关键组合
scp -rp 能保留权限和时间,但没法删目标端多出来的旧文件;rsync -a(等价于 -rlptgoD)一步到位:
-
-a包含递归、保留符号链接、权限、属主、时间戳、设备文件等——部署服务时少踩一半坑 -
--delete表示“目标端有、源端没有的文件,给我删掉”,配合-a才算真正同步(否则只是追加) - 但
--delete危险:如果源路径末尾漏了/,比如写成rsync -a --delete /data user@host:/backup,它会把/backup/data当作目标,然后删掉整个/backup下非data的所有内容
最稳妥写法永远是:源路径带尾部斜杠 /data/,目标路径不带或带都行,但语义明确——同步的是 /data/ 里的内容,不是 /data 这个目录本身。











