ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Linux文件传输实战:scp、rsync与sftp用法及避坑指南

Linux文件传输实战:scp、rsync与sftp用法及避坑指南 本地文件传到Linux服务器大概是运维生涯里重复次数最多的一个动作。我刚接触Linux那会儿习惯在Windows上用各种图形工具拖来拖去后来上了纯命令行环境才发现老老实实用scp、rsync、sftp才是效率和安全兼得的路子。这篇文章不是教科书式铺开讲而是按我实际工作中的使用频率把单次传输、增量同步、交互式操作、跨系统传输这四类场景一次讲透顺带把连接失败、权限混乱、断线重传、文件校验这些坑提前排掉。适合刚入门服务器运维的读者也适合那些已经会用scp但想把rsync和sftp用得明明白白的朋友。1. 动手前的准备先确认网络与SSH服务没问题很多人一上来就敲scp命令结果卡在Connection refused或者Operation timed out然后开始怀疑人生。其实90%的传输失败都不是命令写错了而是前置条件没确认好。我自己的习惯是任何传输动作之前先花一分钟做三项检查省下的时间远不止一分钟。1.1 网络连通性与22端口探测第一项检查是ping通不通。ping不通说明机器都不在一个可达的网络里后面什么都别谈。ping通了不代表就能传文件因为文件传输走的是TCP端口最常见的就是SSH默认的22端口。很多时候ping是通的但22端口被云平台安全组、iptables或者firewalld拦住了。判断端口通不通Linux下我用nc -vzWindows下用telnet效果一样ping -c 4 192.168.1.100 nc -vz -w 3 192.168.1.100 22如果nc返回open说明端口放行了。如果是Connection refused通常是SSH服务没起来如果是timeout那就是防火墙或安全组拦住了。这里有个经验云服务器先查控制台里的安全组规则物理机再查本机防火墙。很多新手在云服务器上排查半天iptables结果发现是安全组没放行方向完全搞反了。1.2 账号权限与免密登录配置第二项检查是目标目录的写权限。传文件之前先想想你用什么用户登录、那个用户在远端有没有目标目录的写权限。默认root登录在很多发行版里是被禁用的PermitRootLogin默认是prohibit-password也就是禁密码登录。如果确实要root直接传得改/etc/ssh/sshd_config里的配置再重启sshd如果不想动服务器配置就直接用普通用户传进去后再sudo调整。第三项是考虑要不要配免密登录。如果你只是手动传一两次输密码没毛病但如果要做定时同步、写自动化脚本密码一定得换成密钥认证。生成密钥并推送到服务器上ssh-keygen -t ed25519 ssh-copy-id -p 2222 ops192.168.1.100生成密钥时我推荐ed25519比rsa短安全性也好。唯一要注意的是老版本CentOS 6或更早的系统可能不支持ed25519遇到老机器就老老实实ssh-keygen -t rsa -b 4096。配好免密之后scp、rsync、sftp就全都跟着免密了脚本里的坑直接少掉一半。注意免密登录测试时如果服务器返回Host key verification failed说明这台服务器的指纹没在你本机的known_hosts里或者是服务器重装系统后指纹变了。确认是可靠服务器后用ssh-keygen -R 服务器IP清掉旧指纹再连一次。2. scp单次文件传输最顺手的命令scp全称Secure Copy基于SSH协议做加密复制。它的语法和cp很像最大的区别就是目标主机用用户名主机地址:路径这种冒号分隔写法。只要把SSH那套端口、密钥、密码搞明白了scp就是最直观的上传下载工具。2.1 scp基础用法与关键参数一次典型的上传是这样写的scp -P 2222 -C backup.tar.gz ops192.168.1.100:/data/backups/把本地的backup.tar.gz传到192.168.1.100的/data/backups/目录下文件名保持原名。这里的-P 2222是指定SSH端口注意是大写P小写-p意思是保留文件的修改时间和权限两个参数功能完全不同我见过不少人在这个点上翻车。参数表整理一下参数作用示例-P指定远端SSH端口大写scp -P 2222 file ...-r递归复制目录传目录必须加scp -r ./images ...-C传输时启用压缩文本类文件收益明显scp -C file.tar ...-l限速单位是Kbit/s注意是bit不是Bytescp -l 8192 file ...-i指定私钥文件scp -i ~/.ssh/id_ed25519 file ...-p保留原文件的修改时间与权限位scp -p file ...很多人以为既然传的是压缩包-C加不加都行其实tar包和文本文件压缩后体积能差不少。反过来如果传的是jpg、mp4这种已经压缩过的文件-C不仅没用反而白白消耗CPU这时候就别加了。2.2 目录传输、多文件与通配符的经典坑目录传输一定要加法-r不加就报错omitting directory。多个文件可以一次传把源写在前面目标写在最后scp file1.txt file2.txt config.conf ops192.168.1.100:/data/通配符这块要小心。scp *.log userhost:/logs/这个命令里的星号会在本地Shell展开你本地有什么.log就传什么。如果你想传的是服务器上某个目录里的.log文件得把星号用引号包住让它到远端再展开scp *.log ops192.168.1.100:/var/log/这个引号杀过很多新手其实原理很简单Shell先处理没加引号的部分加了引号的内容原样传给远端命令去解析。还有一个特别容易忽略的坑scp不会自动创建目标目录。目标路径写成/data/backups/如果这个目录在服务器上不存在你会直接收到No such file or directory。正确做法是先SSH上去把目录建好或者用ssh opshost mkdir -p /data/backups一次性搞定。另外scp -r复制目录时如果目录里有软链接默认会跟着链接把真实文件内容复制过去而不是保留一个链接。这个行为跟rsync很不一样想保留链接结构的话到下节用rsync才是正确答案。scp上传还会保留本地的权限位所以Windows里常见的666、777这类宽松权限传到Linux上之后建议立刻chmod 644或chmod 750收敛一下别给攻击者送权限。3. rsync增量同步与断点续传的正确姿势scp最大的毛病就是每次都是全量复制。传一次两次没问题但你要是天天把本地项目同步到测试服务器或者往服务器上传一个几十GB的数据库备份就会发现scp实在太傻了文件没变它也从头传一遍网络一断又从头再来。这个场景下rsync是正解。3.1 为什么批量和大文件场景优先用rsyncrsync的工作方式一句话概括就是只传变化的部分。它默认会根据文件的大小和修改时间判断两个文件是否一致如果一致就跳过还可以加--checksum参数通过校验内容来判断准确率更高但会额外消耗资源。大文件传输中断后--partial参数会保留已经传完的那部分下次续传时只补剩下的体验和迅雷断点续传类似。拿scp和rsync做个对比差距一目了然维度scprsync增量传输不支持每次全量支持只传差异部分断点续传不支持--partial保留已传部分排除文件不支持--exclude支持删除多余文件不支持--delete支持保留软链接会跟链接复制真实文件-a模式保留链接本身定时同步不适合非常适合用生活化类比就是scp像你把整本书复印一遍给朋友rsync是每次只把改过的那几页发过去。书页数多了以后差距根本不是一倍两倍而是数量级的。3.2 rsync核心参数与一条能直接用的命令先看一条我常用的同步命令rsync -avzP --bwlimit10240 --timeout60 ./site/ ops192.168.1.100:/var/www/site/拆开讲一下-a是归档模式递归传输并保留权限、时间戳、软链接等属性等价于-rlptgoD一组参数的合集-v是详细输出能在屏幕上看到传输列表-z是传输时压缩和内网传输配合效果很好但如果源文件是视频、图片这种已经压缩过的加了反而慢可以不加-P是--partial --progress的合写保留部分文件并显示进度断点续传就靠它--bwlimit10240是限速单位是KB/s10240KB/s就是10MB/s。为什么要限速曾经有一次我半夜做全量同步没限速直接把办公室出口带宽占满了第二天上班同事全都卡在登录页。带宽是公共资源尤其是线上服务器一定要控速--timeout60是设置超时时间网络抖动时连接能自动断掉而不是无限卡死。路径后面的斜杠是rsync的另一个大坑方向看起来差不多实际语义完全不同rsync -avz /data/ ops192.168.1.100:/backup/ rsync -avz /data ops192.168.1.100:/backup/第一条命令/data/带了末尾斜杠意思是复制data目录里的内容到/backup/下面不会额外创建data目录第二条命令/data没带斜杠意思是把data目录本身复制过去结果会是/backup/data。到底用哪个取决于你的目的但搞混的后果很严重批量同步到错误层级日志、配置文件会散落得到处都是。--delete也是一个高危参数。它会把目标端存在、源端不存在的内容删掉目的是让两边完全一致。用之前一定要想清楚源端是不是权威副本。我的习惯是先加-n做一次空跑只显示会执行什么操作但不动任何文件rsync -avz --delete -n ./site/ ops192.168.1.100:/var/www/site/空跑输出确认无误后再把-n去掉真正执行。另外如果服务器上挂了NAS存储临时目录rsync同样可以把本地数据以增量的方式推到挂载点避免每次全量拷贝拖慢应用。4. sftp需要边看边传文件时的交互式工具scp适合“确定把A传到B”的机械动作rsync适合“保持两个目录一致”的同步动作。但有时候你根本记不清服务器目录长什么样需要先看看远端有什么再决定往哪传、传完再确认一下。这种场景sftp才是趁手的工具。4.1 sftp交互式会话与put/get命令sftp同样基于SSH协议安全性没得说。进入交互模式的方式和ssh几乎一样sftp -P 2222 ops192.168.1.100进去之后本地命令前面要加l远端命令不带前缀。这两个概念最容易混淆我在下面列一下常用操作命令作用lpwd / lls / lcd查看本地目录、列本地文件、切换本地目录pwd / ls / cd查看远端目录、列远端文件、切换远端目录put local.txt上传本地文件到当前远端目录get remote.txt下载远端文件到当前本地目录put *.log批量上传匹配文件get -r /data/logs递归下载整个目录chmod / mkdir / rm远端权限修改、建目录、删除文件用sftp最舒服的一点是你能先用ls确认远端文件名和目录结构再决定传给谁。我记得有一次要覆盖服务器上的一个配置文件直接用scp敲路径结果目标目录名记错了文件传到了别的目录应用起不来。后来改成sftp先cd /etc/nginx/再ls看一下确认无误再put就再没出过这种低级事故。4.2 sftp批量操作与批处理脚本sftp也支持批处理适合需要定时上传几个固定文件的场景。写一个batch文件内容就是sftp交互时要敲的命令cd /data put backup.tar.gz bye然后在Shell里执行sftp -b batch.txt ops192.168.1.100注意批处理模式下如果服务器要求输密码还是会停下来等你。所以自动化脚本里尽量配合密钥认证否则人不在电脑前任务就卡住了。另外batch文件里不要写rm、rmdir这类危险操作万一文件内容写错了定时任务跑起来可能把远端数据清了这比scp误传还要难收拾。5. 实战组合大文件、批量同步与跨系统传输的完整方案单独用某个工具能解决大部分问题但实际工作中经常会遇到“scp太慢、rsync不会用、文件还带中文名”这种混合场景。下面这几个组合方案是我自己摸索出来的基本覆盖了最常见的三种复杂情况。5.1 大量小文件先打包再传输海量小文件的场景直接scp或rsync都会很痛苦。小文件数量多每传一个都要经过SSH通道往返效率被严重拖低。正确思路是先打包再传输更高级的做法是压根不让压缩包落盘直接管道流式传tar czf - ./images/ | ssh ops192.168.1.100 cat /data/images.tar.gz这条命令把images目录打包输出到标准输出通过SSH管道把数据流写到服务器上。好处是本地不占临时磁盘空间传完直接就是一份完整的压缩包。缺点是如果网络断了管道流中断就只能重来。所以这个方式适合中等大小的文件集如果是几十GB的大目录我会选择先tar到本地磁盘再用rsync加--partial来断点续传稳妥得多。5.2 从服务器拉回文件的方向问题很多人只研究了本地传到服务器反向操作时又把参数绕晕了。其实方向就是换一下源和目标的位置scp ops192.168.1.100:/data/output.log /local/path/ rsync -avzP ops192.168.1.100:/data/ /local/backup/ sftp get -r /data/logs/ ./download/核心逻辑是记住“冒号跟在哪边哪边就是远端”。scp命令里本地路径在左边还是右边决定了你是上传还是下载。这个思路理清了远程传输就不会再犯方向错误。5.3 Windows与Linux之间的特殊注意事项如果你的本机是Windows有几个本地文件传到Linux时特有的大坑要提前预防。第一个是换行符问题。Windows记事本写的文本脚本换行符是CRLFLinux下是LF。一个脚本传到Linux上跑可能会报错/bin/bash^M: bad interpreter就是CRLF在作怪。处理方式sed -i s/\r$// script.sh # 或者 dos2unix script.sh第二个是中文文件名和编码问题。Windows中文环境默认GBK编码Linux是UTF-8中文文件名传上去经常乱码或者变成一堆问号。我的建议是打包传用zip -r打包时注意编码兼容性避免用图形工具默认的编码方式。如果只是零散几个文件尽量改成英文文件名再传能省下不少心。第三个是权限位问题。Windows没有chmod的概念Windows下创建的文件传到Linux权限可能变成666或777这在生产环境是不可接受的。传上去后立刻执行chmod别等着应用报权限错误再追查。5.4 定时增量同步脚本参考rsync配合cron做定时同步是服务器运维里很标准的玩法。下面这个脚本我一直在用#!/bin/bash rsync -avz --delete --partial --bwlimit20480 /data/www/ ops192.168.1.100:/backup/www/ /var/log/sync.log 21加入crontab30 2 * * * /opt/scripts/sync.sh每天凌晨2点半自动同步一次。这里有几个细节日志一定要重定向到文件否则cron执行时报错会发邮件到本地邮箱很多时候根本没人看限速设成20480KB/s也就是20MB/s避开业务高峰期的带宽占用--delete表示以本地为权威远端多余的旧文件会被清理适合做镜像备份。如果你想要保留历史版本而不是严格镜像就不要加--delete改用带时间戳的快照目录。6. 常见问题与排查技巧从连接到校验的避坑清单传文件这件事出问题不可怕可怕的是没人知道错在哪。我把自己踩过的和帮别人排查过的典型问题整理成了速查表按“连接阶段、传输阶段、验证阶段”三个位置找原因。6.1 连接失败与认证异常的排查路径连接阶段的问题多半出在网络和SSH服务上按表格里的步骤来基本五分钟内能定位错误现象常见原因排查命令Connection refusedSSH服务没起 / 端口不对systemctl status sshd、ss -lntp | grep 22Operation timed out防火墙、安全组拦截nc -vz 主机 22、检查firewalld/iptablesPermission denied (publickey,password)认证失败、密码登录被禁查看/var/log/secure确认PasswordAuthenticationHost key verification failed服务器指纹变更ssh-keygen -R 主机IP后重新连接Too many authentication failures本机密钥太多被拒绝ssh -o IdentitiesOnlyyes或指定-i第六条容易被忽略。如果你的~/.ssh目录下有一堆密钥默认情况下SSH客户端会挨个尝试超过上限就会被服务器拒绝。指定明确的-i参数是最快的解决办法。6.2 传输中断、速度慢与数据完整性校验传输过程出问题最常见的是大文件中断。scp中断了只能从头再来rsync加--partial才能保证续传能力。这也是为什么大文件我永远推荐rsync而不是scp的原因。速度慢要分情况看。文本类文件可以开-C压缩传输量能明显降下来但jpg、视频、压缩包这类已经压缩过的数据再压缩纯属浪费CPU。还有一个常被忽视的问题服务器sshd配置里DNS反向解析默认开启会让每次连接变慢对于内网环境可以安全地关掉在sshd_config里设置UseDNS no再重启sshd。如果你发现SSH登录本身就慢这个配置大概率是元凶。传完之后绝对不要直接离开。尤其是配置文件、数据库备份、代码包一定要做校验。最简单可靠的方式是对比文件哈希# 本地计算 md5sum backup.tar.gz # 服务器上计算 md5sum /data/backups/backup.tar.gz两边输出的哈希值一致才是真的传完整了。追求更高的严谨度可以用sha256sum替代md5sum命令用法一模一样只是输出更长、碰撞概率更低。日常场景md5足够了数据库备份这种关键数据我会用sha256。我自己现在养成两个习惯一是传小文件前先想清楚这次该用scp还是rsync凡是需要重复同步的一律写rsync脚本而不是手动敲scp二是传完任何重要文件都在本地和远端各跑一次校验命令再收工。这两个习惯看着不起眼但真能让你少熬好几次夜。
返回列表