你在服务器上跑完实验,生成了一堆结果文件,现在想拷到本地看看。或者服务器上有个项目目录,你想整个搬下来。
这件事听起来简单,但第一次做的时候总会卡在命令格式上。这篇文章讲三种方式:scp 直接拷 、先压缩再拷 、rsync 增量同步,从简单到高效,看完就能用。
一、先搞清楚一件事:方向
不管用哪个工具,核心格式都是:
复制代码
命令 [从哪里] [到哪里]
从服务器拷到本地,"从哪里"就是服务器路径,"到哪里"就是本地路径。服务器路径的写法是:
复制代码
用户名@服务器地址:远程路径
比如root@192.168.1.100:/home/data/results/,这个格式贯穿全文,记住就行。
三种方式都是"从服务器到本地"这一个方向,区别只在于传输策略:直接拷、压缩后拷、增量同步。
二、scp:最简单的拷贝
scp(Secure Copy)是基于 SSH 的文件拷贝工具,几乎所有 Linux/Mac 都自带,不需要额外安装。
2.1 拷贝用法
(1) 拷贝单个文件
例如,将服务器的 /home/data/result.csv 拷贝到本地当前目录。
bash
复制代码
scp root@192.168.1.100:/home/data/result.csv ./
(2) 拷贝整个目录
加 -r(recursive,递归):
bash
复制代码
scp -r root@192.168.1.100:/home/data/results/ ./results/
注意远程路径末尾的 /:加不加都行,scp 不敏感。但本地目标路径如果不存在,scp 会自动创建。
2.2 指定端口
如果服务器 SSH 不是默认的 22 端口:
bash
复制代码
scp -P 2222 -r root@192.168.1.100:/home/data/results/ ./results/
注意是大写 -P,这一点和 ssh 的小写 -p 不一样。
2.3 scp 的局限
scp 够用,但有两个问题:
每次全量拷贝,1000 个文件改了 2 个,再 scp 还是传全部 1000 个
文件多了很慢 ,scp 是逐个文件建立传输的,文件数量多时开销大,即使每个文件很小。文件少的时候无所谓,但目录一大就该换方案了。
三、先压缩再拷:文件多的时候快很多
当目录里有成百上千个小文件时,先在服务器上打包压缩成一个文件,再 scp 拉下来 ,比直接 scp -r 快得多。
原因很直觉:传 1 个 100MB 的压缩包,比传 10000 个小文件快。因为省掉了逐个文件建立连接的开销,而且压缩后体积更小。
左边逐个文件传输,连接开销大、速度慢;右边打包成一个文件再传,一次连接搞定,体积还更小。文件越多,差距越明显。
3.1 完整流程
(1) 第一步:SSH 登录服务器,压缩目录
bash
复制代码
ssh root@192.168.1.100
cd /home/data
tar -czf results.tar.gz results/
tar -czf 三个参数:c 创建归档、z 用 gzip 压缩、f 指定文件名。
(2) 第二步:回到本地,scp 拉压缩包
现在只有一个压缩包文件,传输很快。
bash
复制代码
scp root@192.168.1.100:/home/data/results.tar.gz ./
(3) 第三步:本地解压
bash
复制代码
tar -xzf results.tar.gz
x 是解压(extract),其他参数和压缩时一样。
3.2 一条命令搞定(进阶)
不想手动登录服务器?可以用 SSH 远程执行压缩,再管道直接拉下来:
bash
复制代码
ssh root@192.168.1.100 "tar -czf - /home/data/results/" | tar -xzf - -C ./
这条命令做了三件事:远程压缩 → 通过 SSH 管道传输 → 本地直接解压。中间不落地临时文件。
-czf - 里的 - 表示输出到标准输出(而不是写文件),本地的 tar -xzf - 从标准输入读取,-C ./ 指定解压到当前目录。
3.3 压缩格式怎么选
格式
命令
压缩率
速度
.tar.gz
tar -czf
中等
快,最常用
.tar.bz2
tar -cjf
较高
较慢
.zip
zip -r file.zip dir/
中等
快,Windows 友好
日常用 .tar.gz 就行,压缩速度和压缩率的平衡最好。
3.4 别忘了清理服务器上的压缩包
拷完之后,服务器上那个临时压缩包可以删掉:
bash
复制代码
ssh root@192.168.1.100 "rm /home/data/results.tar.gz"
四、rsync:只传有变化的部分
rsync 是 scp 的升级版。它会对比本地和远程的文件差异,只传输有变化的部分。第一次全量传,之后增量传,速度快很多。
4.1 基本用法
bash
复制代码
rsync -avz root@192.168.1.100:/home/data/results/ ./results/
三个常用参数:
参数
含义
-a
archive 模式,保留权限、时间戳、子目录等,最常用
-v
verbose,显示传输过程
-z
传输时压缩,网络慢的时候有用
4.2 远程路径末尾的 / 很重要
这是 rsync 和 scp 最大的区别,也是新手最容易踩的坑:
bash
复制代码
# 末尾有 /:把 results 目录里的内容拷到本地 ./results/
rsync -avz root@server:/home/data/results/ ./results/
# 末尾没 /:把 results 这个目录本身拷过来,会变成 ./results/results/
rsync -avz root@server:/home/data/results ./results/
建议:源路径末尾加 /,这样行为更直觉:"把里面的东西同步过来"。
4.3 指定端口
bash
复制代码
rsync -avz -e "ssh -p 2222" root@server:/home/data/results/ ./results/
4.4 排除某些文件
不想拷日志、缓存之类的:
bash
复制代码
rsync -avz --exclude="*.log" --exclude="__pycache__/" root@server:/home/data/results/ ./results/
4.5 先预览,再执行
不确定会传哪些文件?加 --dry-run:
bash
复制代码
rsync -avz --dry-run root@server:/home/data/results/ ./results/
它会列出将要传输的文件,但不会真的传。养成习惯,大目录同步前先 dry-run 看一眼。
五、怎么选
场景
推荐
理由
临时拷一两个文件
scp
最简单,不用想
目录里几千个小文件
tar 压缩 + scp
打包成一个文件传,快很多
大目录,之后还要反复同步
rsync
首次全量,之后只传变化的
想排除某些文件
rsync
--exclude 很方便
服务器没装 rsync
tar + scp
只依赖 SSH,哪都能用
一句话总结:偶尔拷用 scp,文件多先压缩,长期同步用 rsync。
以后再遇到"从服务器拷文件"的需求,顺着这张决策图走一遍,就知道该用哪个工具了。
六、实用补充
6.1 从本地传到服务器
把"从哪里"和"到哪里"调换位置就行:
bash
复制代码
# scp
scp -r ./local_dir/ root@server:/home/data/
# rsync
rsync -avz ./local_dir/ root@server:/home/data/local_dir/
6.2 配合 SSH 配置简化命令
如果你在 ~/.ssh/config 里配了服务器别名:
复制代码
Host myserver
HostName 192.168.1.100
User root
Port 22
那命令就可以简化成:
bash
复制代码
rsync -avz myserver:/home/data/results/ ./results/
不用每次敲 IP 和用户名了。
6.3 传输大文件时想看进度
bash
复制代码
rsync -avz --progress root@server:/home/data/bigfile.tar.gz ./
--progress 会显示每个文件的传输进度和速度。
七、总结
scp 是最简单的远程拷贝,scp -r 拷目录,适合临时传几个文件
文件多的时候先压缩 :服务器上 tar -czf 打包,scp 拉下来,本地 tar -xzf 解压
rsync 是增量同步工具,-avz 三件套记住就行,长期同步场景首选
rsync 的源路径 末尾加 /,避免多嵌套一层目录
大目录同步前用 --dry-run 先预览
配合 ~/.ssh/config 可以大幅简化命令