Ubuntu服务器互传文件夹实战:从scp到rsync与安全加固 两台 Ubuntu 服务器之间传文件夹这活儿听起来简单真要传好、传稳、传得不出幺蛾子里面门道不少。我这些年帮客户迁移数据、同步备份踩过的坑能绕机房一圈。今天不聊虚的直接把这套“服务器互传文件夹”的完整实战经验拆开讲透从最基本的命令到增量同步、断点续传、权限保留、安全加固全部按真实操作环境和思路来。1. 传文件夹这件事先想清楚三个问题动手敲命令之前我建议你花两分钟想明白自己的实际场景。同样是两台 Ubuntu 服务器之间互传文件夹一次性拷贝、定期增量备份、双向数据同步这三者的技术选型完全不同。盲目套用一个命令轻则效率低重则数据错乱。1.1 有多少数据、传多少次、谁来操作先说数据量层面。如果你只是偶尔手动传个小目录比如几百兆、一两个 GB那么scp就够用了简单直接不需要额外装任何东西。但如果目录里有几十万个文件、几十 GB 甚至上 TB 的数据那就必须上rsync否则你会在终端前等到怀疑人生。传输频率也很关键。如果是“每天凌晨自动把 A 服务器的日志同步到 B 服务器”那就不能靠手动敲命令得写脚本配合 cron 定时任务同时还要考虑增量同步能力。如果只有一次性的搬迁任务比如机房迁移、服务器换新那重点就是完整性校验和权限保留而不是同步效率。最后说操作者。如果是你自己在终端里操作交互式输入密码没问题。但如果你要写成自动化脚本那必须配置 SSH 密钥免密登录否则脚本一跑就卡在密码输入那里挂机挂到天荒地老。1.2 主流方案对照scp、rsync、sftp、NFS 怎么选我直接给一个对比表这是我平时给团队内部做培训用的标准表方案适合场景增量传输断点续传权限保留上手难度scp小规模一次性拷贝不支持不支持基本保留不保留属主/时间戳细节极低rsync中大规模同步/备份支持支持需配合参数或工具完整保留中等sftp交互式管理远程文件不支持支持部分客户端一般低NFS/Samba常驻挂载、实时共享本身就是实时访问不适用取决于配置高日常场景里我 90% 以上的互传需求都用rsync搞定。scp偶尔用于应急或顺手传个小文件。sftp适合你不想开 SSH 完整权限、只想让对端用户管理特定目录的场景。NFS 属于“把远程目录当本地盘用”的思路适合持续共享但不适合一次性搬数据。1.3 一个容易被忽略的前提SSH 配置以上所有命令scp、rsync、sftp默认都走 SSH 通道所以你得先确认两台服务器的 SSH 服务是正常的。说白了Ubuntu 之间互传文件夹本质上就是“通过 SSH 通道操作对方的文件系统”。我遇到过不少新手在阿里云或者腾讯云上开了服务器安全组端口却忘了装 OpenSSH Server结果客户端一通操作猛如虎一看报错全是Connection refused。Ubuntu 桌面版默认没装 SSH 服务端服务器版看安装选项。没装的话先执行sudo apt update sudo apt install openssh-server -y sudo systemctl enable --now ssh确认服务状态sudo systemctl status ssh看到active (running)就放心了。另外提醒一句很多云厂商的安全组默认只放行 80/443/22 这类端口22 端口一般没问题但你的 SSH 如果改了端口记得同步放行安全组。2. scp 快速上手适合一次性拷贝的轻量方案scp是 Secure Copy 的缩写利用 SSH 协议加密传输文件。它的语法和cp非常像只是在源路径或目标路径前面加上了“用户名主机地址:”的前缀。如果你只想完成一次简单的文件夹拷贝这是最快的路径。2.1 scp 基础命令与参数解析最基本的命令长这样scp -r /home/user/data 用户名目标IP:/home/user/这里的-r表示递归复制目录。如果你不加这个参数直接复制目录会报错omitting directory因为scp默认只处理文件。几个我常用的参数-P 端口号指定 SSH 端口注意是大写 P。默认 22 端口可以省略。-C开启压缩传输。如果你的网络带宽有限这是个好东西但也会增加 CPU 负载。文本类文件压缩率很高压缩视频图片类文件反而浪费 CPU。-i 密钥文件路径指定私钥文件登录适合非默认密钥名的场景。-l 带宽限制以 Kbit/s 为单位限制带宽。比如你不想让传输占满机房带宽可以加-l 8192就是把传输带宽限制在 8Mbps 左右。举个例子把本机/data目录传到 IP 为192.168.1.10的服务器SSH 端口为2222同时启用压缩scp -r -C -P 2222 /data 用户名192.168.1.10:/backup/注意目标路径末尾的斜杠/backup/表示把/data目录整体放进/backup下面形成/backup/data。如果目标路径写成/backup且这个目录已存在效果是一样的。但如果/backup不存在有些版本的 scp 行为可能不同稳妥起见还是写清/backup/data这种完整路径更可控。2.2 scp 的局限与替代场景scp最大的问题有三个第一它不支持增量同步。每次传的都是全量数据哪怕你上次已经传了 99% 的内容它还是会完整复刻一遍。第二它不支持断点续传。传了一半网络断了对不起重新来。第三它默认不保留原始文件的属主owner、时间戳等元数据。你传过去之后文件的时间戳变成传输时刻的时间对某些需要保留修改时间的场景很致命。有人会问那为什么还要用它答案很简单快、稳、简单。对于几百 MB 到几个 GB 的一次性传输scp开箱即用零学习成本。你要是为了传个小目录专门去学 rsync 的参数那反而是在浪费精力。还有一种场景我经常用scp就是“临时从 A 服务器拉一个文件到本地再推到 B 服务器”。虽然路径绕了一点但在两台服务器之间没法直接连通比如处在不同内网的时候本地中转是最快的解法。2.3 一个实用技巧用 tar 配合 scp 保留权限和时间戳如果你既想用scp的简单又想保留完整的权限和时间戳可以在传之前先打个包。步子很简单通过管道把tar和scp串起来tar czf - /data | ssh 用户名目标IP tar xzf - -C /backup这条命令的意思是把/data目录打包并通过 ssh 通道直接发送到目标服务器然后在目标服务器上解包到/backup目录。它比scp -r好的地方在于tar保存了文件的权限、属主、时间戳等元数据而且单个流传输在大目录场景下往往比逐个文件复制更高效因为减少了文件系统调用的开销。这种写法有一个前提目标服务器上也要有tar命令Ubuntu 系统默认都有这个不用担心。如果想看你传输的过程中发生了什么把czf改成czvf也就是加一个v就能看到每个文件的处理过程。注意如果两台服务器之间的网络不太稳定建议先测一下再跑大数据量任务。tar 流式传输一旦中断整个管道就断了没有断点续传能力。3. rsync 才是主力增量同步与断点续传的完整实操如果你需要经常在两台服务器之间同步目录或者数据量大到scp实在扛不住那rsync就是你的主力工具。这玩意儿诞生几十年了至今仍是服务器间文件同步的事实标准没有之一。3.1 rsync 核心参数与增量原理rsync的精髓在于“增量传输”。它先把源目录和目标目录做对比找出有差异的部分只传输变化的数据块。这个对比机制叫“滚动校验算法”它在文件未被修改时直接跳过文件只有局部改动时只传改动的那一块效率非常惊人。我日常几乎固定使用的参数组合是rsync -avz --progress 源目录 用户名目标IP:目标路径逐个拆开说-a归档模式等价于-rlptgoD意思是递归复制、保留软链接、保留权限、保留时间戳、保留属主和属组、保留设备文件等特殊文件。通俗讲就是“最大程度地还原源目录的本来面貌”。-vverbose输出详细信息。-z传输时压缩节省带宽原理和 scp 的-C一致。--progress显示传输进度能实时看到文件列表和速度。在增量计算上还需要了解--itemize-changes这个参数它用标志位告诉你每个文件为什么被同步。比如f表示新文件f.sT.......表示文件大小、时间戳发生了变化。这个参数是排查“为什么这个文件被重复传输”的神器。3.2 走 SSH 通道的常规用法与端口处理rsync默认不走 SSH但在 Ubuntu 服务器场景下我们几乎总是让它走 SSH因为 SSH 本身就是加密且安全的。默认命令rsync -avz --progress /data 用户名192.168.1.10:/backup/和scp一样它也支持指定端口rsync -avz --progress -e ssh -p 2222 /data 用户名192.168.1.10:/backup/-e参数是rsync指定远程 shell 的方式。你可以用引号里塞任意 ssh 选项这就让rsync拥有了极强的扩展性。比如你想用特定的私钥rsync -avz --progress -e ssh -p 2222 -i /home/user/.ssh/id_rsa_backup /data 用户名192.168.1.10:/backup/这个-e ssh ...的写法是 rsync 实操里最高频的用法之一一定要记牢。3.3 大目录同步的实战示例排除文件、预演、权限保留来一个我经常在实际业务中用到的大型目录同步示例。假设你要把 A 服务器上的/var/www/html这个站点目录同步到 B 服务器同时排除掉缓存目录、日志目录和临时文件rsync -avz --progress \ -e ssh -p 22 \ --exclude cache/ \ --exclude logs/*.log \ --exclude tmp/ \ /var/www/html/ 用户名192.168.1.10:/var/www/几个解析点--exclude支持相对路径模式cache/表示排除所有名为 cache 的目录*.log表示排除所有 .log 文件。源路径末尾有没有斜杠含义完全不同。/var/www/html/带斜杠表示“把 html 目录下的内容复制过去”目标路径/var/www/下直接出现的是 html 里的文件。如果写成/var/www/html不带斜杠则会把html目录本身复制过去目标是/var/www/html这是一个非常容易踩的坑。正式执行之前强烈建议先跑一遍派演练算dry-run看看 rsync 会做什么操作避免因为粗心导致目标目录被完全覆盖rsync -avzn --progress /var/www/html/ 用户名192.168.1.10:/var/www/-n表示 dry-run它只列出将要执行的传输操作不实际执行。我每次做敏感的大规模同步前都会先跑一下-n确认文件列表没有异常再正式执行。这个习惯救过我很多次。还有一个参数值得专门说--delete。它的作用是“让目标目录与源目录严格保持一致删除目标目录中源目录没有的文件”。用了它就意味着目标目录里多出来的文件会被删掉。我在做镜像同步时非常依赖它把--delete加入命令后整个目录就是源目录的完美副本。但请你注意这个参数很危险加上它之前绝对要三思配合--dry-run跑一次再执行rsync -avz --delete --dry-run /data/ 用户名192.168.1.10:/backup/data/3.4 中断恢复与定时同步脚本实战说个实际情况我曾经在两个机房之间同步 1.2TB 的数据库备份文件带宽只有 100Mbps跑了一整晚中途网络抖动断了。如果是scp那屏一断就得重来前功尽弃。但rsync的好处就在于你再执行一次同样的命令它会立刻识别出哪些文件已经完整传过去了只传剩下的部分相当于是“自然的断点续传”。为了自动化我写过一个非常简单但实用的同步脚本放在/usr/local/bin/sync_backup.sh#!/bin/bash # 增量同步站点目录及数据库备份到备份服务器 SRC/var/www/html DESTbackupuser192.168.1.10:backup/www LOGFILE/var/log/rsync_sync.log rsync -avz --delete --log-file$LOGFILE -e ssh -p 22 -i /root/.ssh/backup_rsa $SRC $DEST # 移除超过 30 天的本地备份日志 find /var/log/rsync*.log -mtime 30 -exec rm {} \;赋予执行权限后放进 crontabchmod x /usr/local/bin/sync_backup.sh crontab -e加入计划任务30 2 * * * /usr/local/bin/sync_backup.sh这个配置会在每天凌晨 2 点 30 分执行同步任务。--log-file参数把每次传输的操作记录到日志方便排查“昨天到底同步了哪些文件”。实战心得rsync退出状态码要看。0 表示成功非 0 表示出错。常见的有 12rsync 本身语法错误、13权限问题、23部分文件传输失败。脚本里加上对退出码的判断出错时直接发送告警到你的手机上比事后查看日志高效得多。比如if [ $? -ne 0 ]; then 发送告警; fi。4. 传输性能监测与安全加固的实操细节效率和安全是服务器互传文件夹逃不开的两个话题。很多教程只会告诉你命令怎么敲不会告诉你实际跑大数据量时怎么保证传输不拖垮生产环境也不会告诉你如何防止意外覆盖。这部分我来说点硬核的。4.1 展示传输进度与速度监测的正确姿势rsync --progress虽然能看到传输进度但输出非常密集尤其在大文件列表下刷屏刷到根本看不清。这时候我一般改用--infoprogress2这个参数只会显示一个总进度条和总速度不会逐文件刷屏rsync -av --infoprogress2 /data/ 用户名192.168.1.10:/backup/输出大概长这样1.2G 3% 78.5MB/s 0:12:30传输百分比、瞬时速度、剩余时间一目了然。这个参数在跑大目录同步时体验非常舒服。如果需要更精细的性能分析rsync支持--stats参数它会在传输结束后统计文件数、总字节数、匹配率等rsync -avz --stats /data/ 用户名192.168.1.10:/backup/最值得关注的是Literal data: 1.2 GB和Matched data: 5.8 GB。匹配率高说明增量同步发挥了大作用你这次实际传输的只有 1.2GB如果全量传输就得跑 7GB。4.2 SSH 密钥认证与免密配置自动化和脚本化部署绕不开免密登录。SSH 密钥认证替代密码认证步骤其实很简单A 服务器上执行ssh-keygen -t rsa -b 4096 -N -f ~/.ssh/id_rsa-t rsa指定算法-b 4096指定密钥长度-N 表示不设置密码短语-f指定保存路径。然后把公钥传到 B 服务器ssh-copy-id 用户名目标IPssh-copy-id会自动把~/.ssh/id_rsa.pub内容追加到目标服务器的~/.ssh/authorized_keys。之后你再执行ssh、scp、rsync就都不会问密码了。为了安全我强烈建议把 SSH 密码认证直接关掉只保留密钥认证。修改/etc/ssh/sshd_configPasswordAuthentication no PubkeyAuthentication yes然后重启 SSH 服务sudo systemctl restart ssh但注意这次操作前务必确认你的密钥能正常登录。有一次我在服务器上配好密钥后没有验证手贱把密码认证关了结果人在机房外密码登录被拒密钥又因为权限问题进不去折腾了一下午。所以建议操作顺序是先在终端测试密钥登录成功再去关闭密码认证并且不要关掉当前这个会话另一个窗口测试通过后再退出会话。4.3 传输过程中命令超时与断连的救急套路我提一个很多人不知道的坑你手动在终端里跑长时间同步一旦本地网络闪断任务就中断了。解决思路是让进程脱离终端运行。以前我会写nohup现在更推荐直接用screen或tmux。比如screen -S sync_session在新建的 screen 窗口里执行同步命令rsync -avz --progress /data/ 用户名192.168.1.10:/backup/然后按CtrlA再按D让会话转入后台也就是 detach。你可以安心关掉终端任务照常跑。回来看时可以重新附加会话screen -r sync_session这个操作简单到不值得一提但在生产环境中救过太多回命我和团队现在跑传输任务时都默认先在 screen 里建一个会话再执行命令。另一个需要注意的是 SSH 长连接的稳定性。你可以通过 ssh 配置来减少长连接断开的情况在~/.ssh/config里加Host * ServerAliveInterval 30 ServerAliveCountMax 10这个配置会让 SSH 每隔 30 秒发送一次心跳探测避免长时间无通信被中间网络设备静默断开。实测下来这种方法对跨运营商网络传输的稳定性提升非常明显。5. 常见问题与排查技巧实录青少年避坑篇这部分内容不是从文档里抄的全是真实操作中遇到过的问题和处理经验。每一条后面我都附了当时的排查思路照着做能帮你省不少时间。5.1 连接超时与端口问题的快速定位症状执行ssh、scp、rsync命令后长时间卡住不动最后报Connection timed out。排查步骤确认目标 IP 能通ping 目标IP。如果 ping 不通大概率是网络路由或安全组问题。确认端口是开的telnet 目标IP 22或nc -vz 目标IP 22。连不通就看是不是忘了装 openssh-server或者防火墙拦截了。确认 SSH 服务监听正常目标服务器上执行ss -tlnp | grep :22能看到0.0.0.0:22就说明服务正常监听。确认目标服务器防火墙sudo ufw statusUbuntu 默认防火墙如果开启需要sudo ufw allow ssh放行。除了网络层面还有一个我遇到过的冷门坑如果两台服务器的系统时间偏差太大SSH 的密钥交换可能失败。遇到诡异的连接问题可以顺手对时一下sudo apt install -y chrony sudo systemctl enable --now chrony时间服务器的配置和这块的联动比较神奇但确实曾解决过一次让我抓狂的 SSH 连接问题。5.2 Permission denied 的三种典型原因及对应解法报错Permission denied (publickey,password)分好几种情况。第一种是验证方式问题目标服务器不允许密码登录而你还在输密码或者你配置的账号没有 SSH 权限。解决办法是改用密钥登录或者检查/etc/ssh/sshd_config里的PasswordAuthentication配置。第二种是账号权限不够你用的用户名没有对应目录的写权限。这很常见比如你想把文件传到/var/www/下面但/var/www/属主是root你用的是普通用户。此时有两种思路一是sudo chown -R 用户名 /var/www/调整属主不推荐在生产环境直接改系统目录的属主二是把目标路径改成普通用户有写权限的目录比如/home/用户名/再后用sudo mv移动到目标位置。第三种是家目录或authorized_keys权限错误这种情况报错很隐蔽就是密钥文件存在、内容也没写错但就是登不进去。原因是 SSH 很需要权限校验严格家目录权限不能超过755.ssh目录权限必须是700authorized_keys权限必须是600如果不对执行chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys chmod g-w ~这个坑十个人有八个会踩第一次配置免密登录时一定要检查权限。5.3 rsync 同步后源文件被误删除的风险与备份策略--delete参数是双刃剑我用它做镜像同步很顺手但也见过同事因为误用了--delete把目标服务器上存储了几年、源端已经清理掉的旧数据全删了现场一度非常尴尬。我的建议是如果目标是备份不要用--delete。直接跑增量同步保留目标端多余文件反而是一种额外的保护。如果目标是镜像需要严格保持一致那用--delete前先做一次-n预演并确认你理解每个被标记删除的文件。永远在目标服务器上留一个最近一次成功同步的快照。我常用的做法是同步完成后再软链一个backup_$(date %F)快照目录配上--link-dest参数可以做“成本几乎为零”的增量快照。快照方式的命令大概是rsync -avz --link-dest/backup/latest /data/ 用户名目标IP:/backup/current/--link-dest会对比目标目录和指定的目录如果文件相同就创建硬链接而不是实质拷贝占用的磁盘空间极小。这是实现“多版本快照”最划算的做法属于 rsync 高阶玩法值得实践一次。5.4 中文文件名与硬链接等冷门问题Ubuntu 服务器之间传文件夹一般不用担心中文文件名。rsync和scp对 UTF-8 编码的中文文件名处理都很正常。但是有一个点要注意如果目标服务器的locale设置有问题某些特殊字符可能在文件系统层面显示异常。我的习惯是先在两边验证echo $LANG如果输出是空的或者是C最好改成en_US.UTF-8或zh_CN.UTF-8。硬链接的问题更隐蔽。如果你在源目录里有很多硬链接文件比如备份软件创建的 dedup 文件普通 rsync 处理起来会非常慢且如果不加参数硬链接关系会丢失文件的硬度变成 1磁盘空间会比源端占用更多。解决办法是加-H参数rsync -avzH /data/ 用户名目标IP:/backup/-H表示保留硬链接。如果遇到“明明文件没变却每回都会全量传输”的诡异现象优先检查是不是文件时间戳不一致。比如你用-t保留时间戳但源目录里很多文件的时间戳本身就是错的可以被-I参数忽略时间戳对比但那会强制全量传输慎用。6. 结尾最后一层实操经验我个人在实际操作中的体会是服务器互传文件夹这件事真正考验人的不是命令本身而是对场景的判断和对细节的把控。同样是rsync一条命令加不加斜杠、加不加--delete、走不走screen结果可能天差地别。每次做大规模同步之前先想清楚三个问题我的数据量多大我的网络带宽多少我的目标目录有没有可能被误操作。想清楚了再出手基本不会翻车。最后再分享一个小技巧在两台服务器之间传超大文件超过 10GB 的数据库备份或镜像建议先用dd或iperf3测一下两台服务器之间的裸带宽确认网络质量再做传输。我发现很多传输失败或者速度慢根本不是工具的问题而是链路上某个中间节点丢包严重。这时候重新拨号换条链路往往比加参数管用得多。工具只是手段稳定传输才是目的希望这篇实战笔记能帮你少走一些弯路。