SCP/Rsync/SFTP:Linux远程文件传输三工具实战指南
干了这么多年运维我几乎每天都要在Linux服务器之间传文件。代码发版要传包日志备份要取数数据库迁移要同步数据碰上半夜线上出问题拷贝文件更是家常便饭。SCP、Rsync、SFTP这三样是Linux下最常用的远程文件传输手段弄熟它们不只是省时间关键时候能救场。这三种工具各有各的脾气SCP简单直接适合一次性拷完就走Rsync擅长增量同步跑第二遍的时候速度优势非常明显SFTP则更像一个加密的“远程文件管理器”适合边浏览边操作。新手经常困惑“到底该用哪个”老手也容易在细节上翻车比如scp的-P和-p搞混、rsync末尾斜杠不一致导致目录层级错误、CentOS上搭SFTP受限目录被权限问题卡住。这篇文章就把这些场景逐个拆开把你需要的命令、参数、排查思路都放到一起照着操作就能解决问题。1. 三类工具的核心思路与适用场景1.1 先搞清楚它们之间的本质区别很多人把SCP、Rsync、SFTP放在一起比较其实它们底层都走SSH协议数据在传输过程中都是加密的从安全性角度看没有本质差别。真正的区别在于各自的定位和设计思路。SCP全称Secure Copy是OpenSSH很早就有的一套复制工具。它的命令格式几乎跟本地cp一模一样只是把目标路径换成“用户名主机名:路径”非常简单粗暴。适合的场景是明确的单次拷贝、文件数量不多、不需要反复执行。它的优势是速度足够快因为没有额外的校验逻辑就是纯流式拷贝。劣势也很明显不支持增量每次都是全量传传一半断了下次得从头再来。Rsync的全称是remote sync重点在“同步”两个字。它的核心逻辑不是复制而是对账先对比源端和目标端的文件差异只传输变化的部分。这个机制使它在“反复执行”“大目录迁移”“定时备份”这几类场景里几乎无法替代。此外它还支持压缩传输、限速、断点续传、排除规则、删除同步功能相当丰富。SFTP全称SSH File Transfer Protocol它不是另一个独立的服务而是SSH协议内置的一个子系统。设计思路更接近FTP登录后在一个交互式Shell里操作可以浏览远程目录、查看文件列表、决定下载哪个、上传哪个。适合的场景是需要人工确认文件列表后操作、想给用户开放一个受限的目录空间但不想给完整Shell权限。因为它基于SSH的子系统服务端只需要开放22端口不需要再单独启一个FTP服务端。1.2 怎么挑选适合当前场景的工具如果你问我“用哪个最好”我的答案是没有最好只有最合适。给你一个我平时判断的参考表。工具传输形式增量传输断点续传交互式浏览典型场景SCP一次性复制不支持不支持不支持传单个文件、临时传包Rsync同步复制支持支持不支持定时备份、目录迁移、镜像同步SFTP分步操作不支持手动续传支持浏览远程目录、开放受限访问简单类比一下SCP像是拿U盘直接拷文件省事但每次都得整个拷Rsync像是网盘同步工具第一次全量同步后面每次只上传改动过的内容SFTP则是打开了一个远程仓库的文件管理器界面你可以慢慢翻看再决定拿哪个。有一点必须强调这三者的安全性其实是一样的因为底层都是SSH加密通道。选择哪个纯粹看操作方式和效率而不是看“哪个更安全”。2. SCP实战最直接的快速传输2.1 上下行文件的完整命令与参数解析SCP基本用法跟cp一致“scp [选项] 源路径 目标路径”只不过路径里带上了主机标识。我把日常用得最多的几个命令列在下面。# 本地上传文件到服务器 scp /home/user/app.tar.gz root192.168.1.100:/opt/backup/ # 从服务器拉取文件到本地 scp root192.168.1.100:/opt/backup/app.tar.gz /home/user/ # 指定端口上传比如SSH端口改成了2222 scp -P 2222 /home/user/app.tar.gz root192.168.1.100:/opt/ # 保留源文件的修改时间、访问权限等属性 scp -p /home/user/app.tar.gz root192.168.1.100:/opt/这里有个几乎是所有新手必踩的坑指定远端端口用大写-P保留属性用的小写-p两者就差一个大小写含义完全不同。我见过不止一次有人写scp -p 2222结果不但没指定端口还把文件属性保留参数给开了最终连接失败还一头雾水。从服务器上拉取单个文件的写法跟上传几乎一样只是把源和目标的位置调换一下。实际操作中我更喜欢先进入本地目标目录再执行拉取命令这样路径写起来更短命令可读性也更好。cd /home/user/downloads scp root192.168.1.100:/data/logs/app.log .注意那个末尾的点代表当前目录意思是把远程的app.log拉取到当前目录下。很多人第一次用的时候容易漏掉这个“点”导致命令缺参数直接报错。2.2 目录批量传输的几个关键选项单个文件用SCP没什么好说的但传输整个目录时必须要加-r参数否则会直接报错“Not a regular file”。这是SCP和cp的差异之一cp复制目录也需要-r但SCP这个参数默认不会带上得手动加。# 递归复制整个目录 scp -r /data/www/ root192.168.1.100:/data/ # 保留文件属性同时启用压缩传输 scp -rpC /data/www/ root192.168.1.100:/data/这里推荐组合使用-r、-p、-C三个参数。解释一下原因-p保留时间戳和权限能让目标端的文件属性跟源端完全一致这在部署代码时特别重要因为时间戳变化会影响一些依赖时间戳判断的构建工具和缓存策略。-C启用压缩在传输文本类文件如HTML、CSS、日志时效果很明显传输体积能减少一半以上但如果传的是已经压缩过的包tar.gz、zip等压缩参数反而会白白消耗CPU这时候就别加-C。如果哪天你需要把服务器上的目录“拉”下来命令同样简单把源和目标调换即可。scp -r root192.168.1.100:/data/www/ /home/user/backup/很多搜索“如何通过scp把文件夹拉下来”的朋友本质上就是在找这条命令。你要记住一个核心源路径是远程、目标路径是本地就是拉反过来就是推。2.3 通过跳板机完成跨网段传输实际生产环境里经常有这样的场景目标服务器处在内网并不直接暴露SSH端口只能通过一台跳板机中转访问。以前大家的做法是先scp到跳板机再在跳板机上scp到目标机完全是折磨人的操作。幸而OpenSSH 7.3以后支持了ProxyJump参数可以直接通过跳板机穿透到内网目标。scp -o ProxyJumpops10.0.0.5 /home/user/app.tar.gz root192.168.1.100:/opt/这样做的原理是本地SSH客户端先跟跳板机建立加密连接然后在这个连接之上再跟目标服务器建立另一层加密连接数据从头到尾都处于加密状态不会在跳板机上有明文落盘。相比“先传到跳板机再转发”的做法省掉了中间环节的存储和二次操作效率高得多。如果你的OpenSSH版本过老不支持ProxyJump那也可以用老式的ProxyCommand方式实现同样的效果只不过配置稍微复杂一点。scp -o ProxyCommand ssh ops10.0.0.5 -W %h:%p /home/user/app.tar.gz root192.168.1.100:/opt/其中-W参数的意思是让跳板机把数据转发到目标主机的指定端口。两种方式效果接近新版本系统直接用ProxyJump就行。3. Rsync实战增量同步与断点续传3.1 rsync底层同步逻辑与高频参数Rsync跟SCP最本质的区别在于它的“增量”能力而这个增量能力来自它两轮校验的设计。第一轮它会比对源端和目标端每个文件的“大小修改时间”不一致的列入待传清单第二轮对于这些待传文件它把文件切分成固定大小的数据块用弱校验和和强校验和做对比找出两端真正不同的块只传输这些差异块。这就是为什么你第二次跑rsync的时候哪怕目录里有一两万个文件它也能在几秒钟内完成校验并告诉你“nothing to send”。相比之下SCP每次都是老老实实把整个文件重传一遍完全没有这种效率。我日常使用rsync最频繁的参数组合是-avz这三个字母包含的意义非同小可。rsync -avz /data/www/ root192.168.1.100:/data/www/-a是归档模式等于“-rlptgoD”的组合意思是递归传输、保留符号链接、保留权限、保留时间戳、保留属主和组信息-v是verbose输出详细信息-z是传输时压缩。这套组合适合绝大多数文件同步场景你基本上可以把它当作默认选项。如果你还要观察传输进度可以加上--progress或--human-readable后者的可读性更好。下面是我实际用过的进度输出示例rsync -avz --progress /data/www/ root192.168.1.100:/data/www/它会在每个文件传输时打印百分比、速率和剩余时间让你对整个过程心里有数。特别是大批量文件同步时没有进度显示心里总是不踏实。3.2 本地目录与远程目录双向同步的姿势Rsync同步有两个方向把本地目录推送到远程push或者把远程目录拉取到本地pull。命令格式分别是# 推本地的/data/www推送到远程服务器的/data/www rsync -avz /data/www/ root192.168.1.100:/data/www/ # 拉远程的/data/backup拉取到本地备份 rsync -avz root192.168.1.100:/data/backup/ /home/user/backup/这里有个细节必须留意路径末尾是否带斜杠含义完全不一样而且这个坑相当隐蔽很多老手也会偶尔翻车。rsync -avz /data/www/ root...:/data/www/ 表示把/data/www目录里的内容同步到目标的/data/www目录里结果就是目标目录下直接是源目录中的各个子目录和文件。rsync -avz /data/www root...:/data/www/ 表示把/data/www这个目录本身同步到目标的/data/www/目录下最终结果是目标目录下多了一层名为www的子目录即/data/www/www。因为一条命令差一个斜杠最终目录结构就多套了一层。如果你打算用脚本做自动化同步建议统一用一个约定我自己的习惯是“源目录带不带斜杠取决于想同步目录内容还是目录本身目标目录统一不带斜杠”。这个困惑很多人都会遇到逐一说明下在同步命令里源路径末尾带/表示只同步目录内的内容不带/表示同步整个目录本身目标路径末尾带不带斜杠对是否嵌套目录不起决定作用起决定作用的始终是源路径。3.3 SSH端口不是22时的rsync写法Rsync使用SSH作为传输通道时如果SSH端口不是默认的22就需要通过-e参数指定ssh命令及端口。rsync -avz -e ssh -p 2222 /data/www/ root192.168.1.100:/data/www/如果你还需要通过跳板机那就在-e参数里加上ProxyJump配置跟前面scp的写法异曲同工。rsync -avz -e ssh -p 2222 -o ProxyJumpops10.0.0.5 /data/www/ root192.168.1.100:/data/www/3.4 排除规则、删除同步与备份模式处理超大目录时我们往往并不需要全量同步所有内容。比如同步网站目录时日志、缓存、临时文件通常没必要一起传。Rsync提供--exclude参数支持多次使用也支持通配符后缀。# 排除所有.log文件以及cache目录 rsync -avz --exclude*.log --exclude/cache/ /data/www/ root192.168.1.100:/data/ # 从文件读取排除规则适合大量排除场景 rsync -avz --exclude-from/home/user/exclude.txt /data/www/ root192.168.1.100:/data/exclude.txt里每行一条规则比如*.log /tmp/ /cache/如果你的目标是让目标端跟源端完全一致那就需要用到--delete参数。它的含义是删除目标端有而源端没有的文件。这个参数很有用但也极其危险必须谨慎使用。rsync -avz --delete /data/www/ root192.168.1.100:/data/www/有多少人因为对--delete理解不深一条命令下去把目标端多余的重要文件全部删了个精光追悔莫及。我的建议是先用不带--delete的dry-run模式跑一遍查看它会做什么确认没问题再真正执行。rsync -avz --delete --dry-run /data/www/ root192.168.1.100:/data/www/加--dry-run或-n后rsync只做模拟演示把将要做的事情列出来但不会真正执行任何传输和删除操作。这是任何涉及删除操作前的必备动作永远不会多余。另外还有一个非常实用的备份组合--backup参数会在覆盖或删除目标文件前先把老文件备份到指定目录这样即使同步出错也能恢复。rsync -avz --delete --backup --backup-dir/data/rsync_backup/$(date %F) /data/www/ root192.168.1.100:/data/www/用日期作为备份目录名称每天同步前自动把将被覆盖的文件存到当天的备份目录里。这个模式特别适合那种“既要完全同步又担心误删”的运维场景是我给重要业务目录做镜像的标配。3.5 断点续传与带宽限制实战Rsync支持断点续传这个能力在SCP身上是完全没有的。大文件传到一半网络断了或者你手动中断了SCP直接留下一个残缺文件接下来要么删掉重传要么眼睁睁看着进度从头再来。Rsync则不会这样“--partial”参数让它保留已传输完毕的部分下次再跑同一命令时会基于这些残留部分继续传。rsync -avz --partial /data/bigfile.tar.gz root192.168.1.100:/data/实际效果是一个10GB的文件传到了63%时网络断了再次执行同一条命令它不会从头开始而是直接从上次中断的位置继续往下传。这个体验用一句话概括就是“传输完成后目标端文件与源文件完整体一致”中途的断点并不会导致文件损坏因为rsync会做完整校验。另一个高频场景是带宽控制。生产环境里的备份或迁移任务往往会占满带宽影响在线业务。rsync提供了--bwlimit参数单位为KB/s。# 限制传输带宽为每秒5MB rsync -avz --partial --bwlimit5000 /data/ root192.168.1.100:/data/我通常会在白天业务繁忙时段限速在1000-2000KB/s深夜业务低峰再放开到5000KB/s甚至不限速。这样既能把数据迁移对线上业务的影响降到最低又不会让同步任务拖成“蜗牛工程”。结合crontab做一个定时增量备份的脚本也非常简单。比如每天凌晨2点把web目录同步到备份机0 2 * * * rsync -avz --partial --delete /data/www/ root192.168.1.100:/data/backup/www/ /var/log/rsync_www.log 21这里建议一定要加--partial因为你根本无法预测凌晨的网络状况。如果你还想更稳一点可以再加--timeout30设置空闲超时时间为30秒连接假死时自动断开避免一个job卡死在那里占用资源。4. SFTP实战交互式管理远程文件4.1 SFTP的底层机制与登录方式SFTP并没有单独的服务端进程它依赖的是SSH服务端的Subsystem配置。简单来说SSH不仅负责远程登录Shell它还可以通过内部子系统提供文件传输功能。你不需要额外安装OpenSSH之外的任何软件只要本地有SSH服务端就天然具备SFTP能力。登录方式是sftp root192.168.1.100如果端口不是22用-oPort参数注意这里是字母o不是scp的大写P。或者直接用sftp -oPort2222 root192.168.1.100效果一样。登录成功后你会看到sftp提示符这表示你已经进入SFTP交互界面可以执行后续的各种文件操作命令。这个会话全程加密与SSH共用认证机制密码或密钥比传统FTP裸奔式的明文传输安全一个量级。4.2 常用交互命令与本地目录切换SFTP的交互命令跟Linux Shell有很多相似之处但也有一组以l开头的本地命令这是很多新手容易弄混的地方。我把最常用的命令整理了一下。分类命令作用远程操作ls、cd、pwd查看远程目录列表、切换目录、当前路径本地操作lls、lcd、lpwd查看本地目录列表、切换本地目录、本地当前路径下载get 文件下载远程文件到本地下载get -r 目录递归下载整个远程目录上传put 文件上传本地文件到远程上传put -r 目录递归上传整个本地目录批量mget / mput匹配通配符批量下载或上传管理rm、mkdir、rename删除、创建目录、重命名远程文件实际操作的体验是这样的sftp lcd /home/user/downloads sftp lpwd Local working directory: /home/user/downloads sftp cd /data/logs sftp get app.log Fetching /data/logs/app.log to app.log sftp get -r /data/www/ /home/user/backup/很多人问“如何把服务器上整个文件夹拉下来”用sftp get -r一条命令就搞定了不需要再装其他工具。递归下载时如果目标文件已经存在SFTP默认会直接覆盖但如果文件在上次传输中不完整建议先删除残缺文件重新下载。mget和mput支持通配符批量操作比如sftp mget *.txt sftp mput *.tar.gz注意mget在下载之前会逐个文件询问确认如果不想被烦可以执行prompt命令关闭交互确认。4.3 CentOS 7下搭建受限目录的SFTP环境这里要单独讲讲“CentOS 7配置SFTP受限目录”这件事因为很多需求并不是给自己用的而是给同事、给客户开放一个专属目录让他们只能在这个目录里上传下载文件不能登录Shell执行其他命令。首先明确思路我们要借助sshd_config里的Match Group或Match User规则对特定用户组的SFTP会话进行ChrootDirectory即把它禁锢在指定目录下和ForceCommand internal-sftp强制使用内置SFTP进程丢弃Shell登录能力限制。步骤一创建用户组和专属用户。groupadd sftpusers useradd -g sftpusers -s /sbin/nologin -d /data/sftp/alice alice echo alice:你的初始密码 | chpasswd这个用户shell设为/sbin/nologin表示它无法通过SSH登录到Shell只能被用于SFTP这类非交互式会话。步骤二创建目录并设置权限。mkdir -p /data/sftp/alice chmod 755 /data/sftp chown root:root /data/sftp chown alice:sftpusers /data/sftp/alice chmod 755 /data/sftp/alice这里有个关键细节ChrootDirectory指定的根目录必须由root用户拥有并且权限不能超过755否则连接会被拒绝。也就是说你只能把用户实际可写空间的根目录往上延伸一层。常见的目录结构是/data/sftp/ root:root755 /data/sftp/alice/ alice:sftpusers755其中/data/sftp/alice这个用户目录可以被alice读写但它没法进入/data/sftp这个层级去操作其他用户的内容更没法往上跳出这个目录。步骤三修改/etc/ssh/sshd_config。在文件末尾追加如下配置。Subsystem sftp internal-sftp Match Group sftpusers ChrootDirectory /data/sftp/%u ForceCommand internal-sftp X11Forwarding no AllowTcpForwarding no然后重启SSHD服务。systemctl restart sshd步骤四用客户端测试。sftp alice192.168.1.100登录成功后你看到的根目录就是/data/sftp/alice用户无法切换到/目录去浏览系统其他文件。这就完成了“受限SFTP环境搭建”。4.4 客户端工具排查与“没有SFTP按钮”的常见原因有朋友问“Tabby使用SSH连接到服务器后怎么没有SFTP按钮”这类问题其实很常见。Tabby、VS Code Remote SSH、FinalShell这类终端工具通常默认只是建立SSH会话SFTP面板属于可选功能。你需要在设置里找到SFTP/文件传输相关的开关手动启用或者直接新建连接时选择SFTP协议而不是SSH。更值得先做的一步是在命令行里直接执行sftp命令验证如果服务器的SFTP子系统能正常连接那就是客户端配置的问题如果连sftp命令都报错那问题多半出在服务端的sshd_config配置。比如Subsystem sftp internal-sftp这一行被误删或写错格式SFTP服务就会无法工作。还有一类情况是SSH服务端配置了ForceCommand internal-sftp但限制范围有误导致普通用户SFTP时直接被拒。最常见的表现就是前面提到的ChrootDirectory权限问题用户所属目录不是root或权限超过755连接就被拒绝。这时候查看/var/log/secure日志通常能看到类似“Bad ownership or modes for chroot directory”的报错照着纠正目录权限即可。5. 常见问题与排查技巧实录5.1 连接不通与端口连不上的排查顺序文件传不上去第一反应不该是怀疑命令写错了而是先确认网络层通不通。排查顺序我通常是这样的先用ping确认主机在线再用telnet或nc确认端口是否开放。ping 192.168.1.100 telnet 192.168.1.100 22 nc -vz 192.168.1.100 22如果端口不通就看服务端sshd是否启动、监听在哪个端口以及防火墙有没有放行。systemctl status sshd ss -tlnp | grep 22 firewall-cmd --list-all如果是云服务器还要检查安全组的入站规则。我曾经排查过一整天才发现是云控制台安全组里根本没放行22端口以外的自定义SSH端口跟服务器内部防火墙完全无关。5.2 SCP传输卡顿或速度过慢的深度原因与对策SCP传文件速度慢未必就是带宽不够。常见原因有两个一个是网络MTU设置太大导致大包被分片或丢弃重传另一个是SSH连接阶段进行反向DNS解析超时。MTU问题最直观的现象是小的文件传输正常一旦传大文件速度骤降甚至卡死。可以尝试在SSH配置里把MTU降低scp -o IPQoScs1 -o ServerAliveInterval30 /data/bigfile.tar.gz root192.168.1.100:/data/更彻底的方法是在服务端的/etc/ssh/sshd_config里加上UseDNS no把连接阶段的反向解析关掉。这个参数默认是yes的时候sshd会尝试把客户端的IP解析成主机名DNS超时可能导致连接或传输卡顿。改成no之后效果立竿见影。echo UseDNS no /etc/ssh/sshd_config systemctl restart sshd另外如果你确认网络本身没问题就是纯粹嫌SCP慢可以换用rsync加压缩和并行参数。Rsync本身就采用增量传输传输效率通常明显优于SCP全量拷贝。5.3 “收到了太大的SFTP包”报错如何处理有一次我遇到了一个特殊的报错“Received message too big”或者你在日志里看到“sftp packet too large”这类提示。这个问题的本质是SFTP协议对包大小有限制而某次传输中数据包超过了上限。常见诱因有几种客户端和服务端的SFTP实现不兼容、网络中间设备防火墙/负载均衡改动了报文、MTU不一致导致重组异常。排查思路先从最简单的做起换一个客户端试试。如果你用的是某个GUI工具换回命令行sftp直接传输往往就能排除客户端实现差异。如果命令行也报错再检查链路MTU尝试在SSH配置里加sftp -o IPQoScs1 -o ServerAliveCountMax2 alice192.168.1.100如果还不行就要考虑是否是代理或中间设备的报文重组干扰必要时把MTU调小一些。这个属于比较冷门的报错多数情况下并非服务器配置错误而是网络链路干扰或客户端差异导致的兼容性问题。5.4 传输中断、断点续传与文件完整性SCP本身不具备断点续传能力传输中断后残留的残缺文件非常具有迷惑性它的大小跟源文件不一样下次再传输时SCP不会自动跳过或续传只会直接覆盖。所以在使用SCP传大文件时我建议传输完成手动检查一下大小。ls -lh /data/app.tar.gz真正需要断点续传的场景建议一开始就用rsync --partial它能自动保留中断进度并在下一次继续。如果不小心用scp传了一半断了最简单的方法是把残留文件删掉重来避免一个不完整的文件被当成完整文件使用这个坑在业务数据迁移时尤其危险。另外要提醒一点SFTP断网后已完成的文件不会丢失但正在传输的那个文件会残留。重新登录后用resume命令可能因客户端实现差异而不可用最简单的办法是删除残缺文件后重新get。这也是我对“SFTP适合轻量操作、Rsync适合重量级同步”理解加深的来源。5.5 权限与认证问题速查权限问题是文件传输失败的重灾区很多看似莫名其妙的现象最终都指向权限。我整理了一张速查表方便大家按图索骥。现象可能原因处理方式Permission denied (publickey)SSH密钥不匹配或权限错误检查私钥权限是否为600公钥是否添加到目标机authorized_keysPermission denied (password)密码错误或服务端禁用了密码登录确认密码或在sshd_config中允许PasswordAuthentication yesPermission denied (publickey,password)用户shell被禁用/sbin/nologin确认为SFTP用户时强制internal-sftp或调整shellBad ownership or modes for chroot directoryChrootDirectory属主不是root或权限超755chown root:root /data/sftp chmod 755 /data/sftp目录无法写入目标目录缺少属主写权限确认用户对目标目录有w权限SELinux状态也值得查看连接超时防火墙、安全组、sshd未启动逐层排查16: ping、端口、防火墙、安全组还有两个隐藏较深的原因SELinux和文件系统挂载选项。CentOS上如果SELinux处于Enforcing状态有时候普通的目录权限看起来没问题但SELinux策略拦截了sshd的写入行为。临时排查可以用getenforce查看但长期使用还是要配置正确的SELinux布尔值比如setsebool -P httpd_can_network_connect 1这类具体根据业务场景选择。最后再分享一个我在实际使用中的体会日常小文件传输图快就直接scp反复要同步的目录一律rsync加--partial需要给别人开分目录权限就搭个受限SFTP。如果哪天发现文件传不顺畅先查网络、端口和权限这三块覆盖了九成以上的故障。文件传输这件事工具越用越熟坑踩得多了后面自然就顺了。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →