Linux文件上传实战:scp、rsync与sftp完全指南
2026/9/18 6:05:32 网站建设 项目流程

前阵子一个刚转运维的朋友找我,说他在云服务器上部署应用,需要把一个离线安装包从本地传上去,结果折腾了半天,最后是打开微信发给自己,再从服务器浏览器里登录微信下载的。这事听着离谱,但确实反映了一个很普遍的问题:很多人知道怎么用Linux,也知道怎么操作服务器,但“怎么把文件从本地上传到远程服务器”这一步,始终是靠猜的。

这篇文章我把日常工作中真正会用到、也真正稳定的文件上传方法完整梳理一遍。不只是给你命令,还会讲清楚每种方式背后的适用场景、参数含义、容易踩的坑,以及上传失败时怎么一步步排查。内容覆盖scp、rsync、sftp、图形化工具、Web面板、大文件断点续传、权限与安全底线这几个方向,无论你是刚接触服务器的萌新,还是已经在生产环境摸爬滚打的运维,都能从中找到直接能用的东西。

1. 先搞清楚传什么、传到哪里——不同场景下的上传思维

1.1 “上传文件”这件事,其实有四种完全不同的场景

我见过太多人上来就问“用什么命令传文件”,但很多问题恰恰出在场景没分清。同样是“上传”,下面这些情况需要的方案完全不同:

  • 本地机器传文件到远程Linux服务器。这是最常见的场景,比如我要把自己电脑上的安装包传到云主机。核心工具就是scp、rsync、sftp这类基于SSH协议的命令行工具。
  • 远程服务器之间互相传文件。比如两台云主机要交换数据,最常见的方式是在一台服务器上用scp或rsync直接推送到另一台,这样不需要先下载到本地再上传。
  • 往服务器上的Web应用上传文件。比如网站后台需要接收用户上传的图片、文档。这种情况根本不是用scp,而是通过应用自身实现的上传接口,涉及的是后端逻辑和Web服务器配置。
  • 往树莓派、虚拟机、NAS这类设备上传。这些设备本质也是Linux系统,但你可能没有公网IP,只能在局域网内操作,连接的细节(比如端口、用户)会稍微特殊。

搞清楚自己属于哪种场景,再往下选工具,才不会出现“用ftp传了半天才发现服务器只开了22端口”这种尴尬。

1.2 工具选型的底层逻辑:安全优先,能用SSH就不用别的

做上传方案选型时,我的判断顺序很固定:SSH可用的情况下,优先选基于SSH的工具。原因很简单:绝大多数Linux服务器默认开启SSH,你不需要额外安装任何服务端软件;SSH通道全程加密,文件内容和传输过程不会明文暴露;权限体系和服务器上的用户体系天然一致,你用什么账号登录,上传的文件就属于哪个用户。

很多教程会让你装vsftpd、配置FTP。但FTP有两个硬伤:一是默认明文传输,账号密码和文件内容都在网络上裸奔;二是现在很多云厂商的安全组默认只放行22端口,你要用FTP还得额外去开放21端口和数据端口,增加了被扫描攻击的面。我的建议是,除非有明确的合规或历史遗留需求,否则直接放弃FTP方案,不要在2025年还把一个带密码的明文协议架在公网上。

还有一类方案是图形化工具,比如FileZilla、WinSCP,它们的底层传输协议走的还是SFTP(SSH File Transfer Protocol),本质上是给命令行工具套了一层可视化界面。这类工具适合文件数量多、路径层级深的场景,操作效率比命令行高,但你在服务器端需要保证sshd服务的Subsystem sftp是开启的。

2. 命令行三件套:scp、rsync、sftp的用法与边界

2.1 scp:最直接的一次性全量复制

scp(Secure Copy)是SSH自带的远程复制命令,用法和cp几乎一样,只是目标地址从本地路径变成了“用户名@主机:路径”。它的核心逻辑是:把文件从A点完整复制到B点,不做增量判断,每次都是全量传输。

最基本的几个用法:

# 单个文件上传 scp /path/to/local_file.tar.gz root@192.168.1.100:/opt/ # 指定端口上传(SSH端口不是默认22时) scp -P 2222 /path/to/local_file.tar.gz root@192.168.1.100:/opt/ # 上传整个目录 scp -r /path/to/local_dir root@192.168.1.100:/opt/

参数说明:-P必须是大写,指定SSH端口;-r递归复制目录;-C开启压缩,适合传文本类文件;-i指定密钥文件。

scp的最大优点是简单、无状态,一条命令就完事。但它的缺点也很明显:

  • 不支持断点续传。传输到一半网络断开,对不起,从头再来。
  • 不做增量校验。哪怕目标位置已经有同样的文件,它也会全部重传一遍。
  • scp命令本身在OpenSSH官方文档中已被标记为“deprecated”(即将弃用),因为它的实现比较老旧,推荐用sftp或rsync替代。不过目前所有主流Linux发行版仍然支持它,短时间不会消失。

我现在的使用习惯是:传一次性的小文件(小于几百MB)用scp,图个快;传大文件、频繁同步用rsync

2.2 rsync:增量同步和断点续传的真正主力

rsync是我个人最依赖的上传工具,没有之一。它最大的价值在于增量同步:传输前会对比源文件和目标文件的差异,只传送发生变化的部分。这听起来复杂,实际效果好得惊人。

# 基础用法:本地目录同步到远程 rsync -avz --progress /path/to/local_dir/ root@192.168.1.100:/opt/remote_dir/ # 指定SSH端口 rsync -avz -e "ssh -p 2222" --progress /path/to/local_dir/ root@192.168.1.100:/opt/ # 断点续传:--partial保留部分传输的文件 rsync -avz --partial --progress /path/to/big_file.tar.gz root@192.168.1.100:/opt/

参数含义这里必须逐个说清楚,因为很多人用rsync出问题就是参数搞错了:

  • -a:归档模式,等价于-rlptgoD,保留权限、时间戳、属主、组、软链接等属性。同步文件到服务器时几乎必加。
  • -v:显示详细信息。
  • -z:传输时压缩,适合带宽受限或者传文本类文件。
  • --progress:显示传输进度和速率,传大文件时一定要加。
  • --partial:保留部分传输的文件。如果不加这个参数,rsync在上传中断后会删掉目标位置的半成品文件,下次重新传。加上之后,下次传输能基于已传的部分继续,本质就是断点续传。
  • --delete:删除目标目录中源目录没有的文件。这个参数要谨慎,用好了是同步利器,用错了会误删数据。我建议新手先别加,等完全理解它再考虑。

还有一个特别容易踩的坑:目录末尾的斜杠

# 带斜杠:把local_dir目录下的内容同步到remote_dir/ rsync -avz /path/to/local_dir/ root@192.168.1.100:/opt/remote_dir/ # 不带斜杠:把local_dir这个目录本身同步到remote_dir/下 rsync -avz /path/to/local_dir root@192.168.1.100:/opt/remote_dir/

第一条命令,如果remote_dir不存在,它会创建一个,然后把local_dir里的内容放进去;第二条命令,会在remote_dir下创建local_dir子目录,再把内容放进去。这两条命令的目标路径结构完全不同,生产环境中因为这个问题把文件同步错位置的情况太常见了,我自己也踩过。

2.3 sftp:交互式操作最适合“一次传多个零散文件”

sftp也是SSH协议家族的一员,但它不像scp那样是纯命令行参数,而是提供一个交互式界面。你连上服务器后,像在本地终端里用cdls一样操作远程目录,用put上传、get下载。

# 连接 sftp root@192.168.1.100 # 连接后执行命令如下 pwd # 查看远程目录 lpwd # 查看本地目录 lcd /path/to/local # 切换本地目录 cd /path/to/remote # 切换远程目录 put local_file.tar.gz # 上传文件 put -r local_dir # 上传目录 get remote_file.tar.gz # 下载文件

sftp支持在交互模式中用reput恢复中断的上传(相当于断点续传),也支持lcdlls这类本地命令操作。更实用的一点是,它非常安全,全程走SSH加密通道,且无需在服务器上额外搭建任何服务。

对日常操作来说,sftp比scp多了一个“可交互”的优势:你可以先连上去看看目标目录长什么样,再决定传到哪里,不会出现连路径都没确认就上传的情况。从自动化脚本的角度,scp和rsync更合适,因为它们能直接塞进shell脚本里跑,而sftp的交互式特性不适合无人值守场景。

2.4 三件套怎么选,一张表说明白

工具适用场景断点续传增量传输交互式操作自动化脚本友好
scp一次性的小文件传输不支持不支持不支持非常适合
rsync大文件、目录同步、长期备份支持(--partial)支持不支持非常适合
sftp零散文件、需要人工确认路径支持(reput)不支持支持一般

如果让我给一个最简单粗暴的选择建议:**不确定用哪个的时候,用rsync。**它几乎能覆盖所有场景,只是命令比scp多几个参数,但换来的是断点续传和增量同步这两个实打实的核心能力。

3. 图形化工具与Web面板:FileZilla、宝塔、网页终端到底怎么选

3.1 FileZilla:适合不习惯命令行的图形化方案

FileZilla是一个免费开源的图形化FTP/SFTP客户端。它底层走SFTP协议时,完全兼容Linux服务器的SSH服务。

最容易被忽略的一个点是连接信息怎么填:

  • 协议选择:必须选SFTP - SSH File Transfer Protocol,不是默认的FTP。
  • 端口填:SSH端口,默认22。如果你服务器改了端口,这里填实际端口,而不是21。
  • 登录类型:用密钥认证选“密钥文件”,并在下方选择对应的私钥文件;用密码认证选“正常”。
  • 字符集:连接Linux服务器时建议设置成UTF-8,否则中文文件名容易乱码。

FileZilla的优点是零学习成本,左右分栏,左边本地文件,右边远程文件,拖拽即可上传。缺点是如果你处理的文件路径很深,拖来拖去反而不如命令行高效;另外传大批量小文件时,图形化界面的连接管理开销比较大,速度会被限制。

3.2 宝塔面板、1Panel这类管理面板:适合服务器上跑业务的人

现在很多服务器上装了宝塔面板或者1Panel这类可视化管理工具,它们自带文件管理器,可以直接在浏览器里上传文件到任意目录。

这类面板的优势在于权限处理比较自动化。你在面板里上传文件,它会自动帮你设置好owner和权限位,基本不会出现“文件上传后网站读不了”的问题。对于非运维岗位的人来说,是最省心的一条路。

但必需说清楚它的不足:

  • 面板本身是一个额外的Web服务,暴露在公网上就多了一个攻击面。面板的登录入口一定要设置强密码,并开启二次验证。
  • 上传大文件时,走的是Web传输通道,受Web服务器限制,通常最大2GB,且断点续传支持不如rsync稳定。
  • 面板文件管理器的底层其实是执行了类似mv、cp、chmod这样的操作,操作过程中不会提示你目标目录大小、磁盘剩余空间这些信息,传大文件前建议自己先看一下。

如果你已经在用面板,日常传配置文件、传小量业务文件完全没问题。但生产环境的大文件、正式版本发布包,我还是推荐用rsync,因为可控性更高,出了问题也更容易排查。

3.3 云厂商的网页VNC和Web终端:应急可用,别当主力

很多云厂商控制台自带网页版VNC或Web终端,这类工具的定位是应急救援通道,比如服务器SSH连不上时可以通过网页终端登录。

用网页终端配合rz命令确实能把本地文件传上去:

# 安装lrzsz yum install lrzsz -y # 或 apt install lrzsz -y # 输入rz命令,会弹出文件选择框 rz # sz是下载,把服务器文件拉到本地 sz /path/to/remote_file

但这里有个非常具体的坑:**网页终端和rz对终端类型有依赖,很多云厂商的Web终端默认不是xterm,rz会弹不出文件选择框,或者上传到一半直接卡死。**我自己在几家主流的云厂商控制台都试过,有的能用、有的不能用,完全看运气。所以我的建议是:网页终端可以用于救急,平时不要依赖,尤其是大文件绝对不要用rz传。

4. 大文件、断点续传与任务中断:rsync配合screen/tmux实战

4.1 传输中断的克星:--partial参数到底怎么工作

传大文件最心疼的时刻,是传了80%网络断了,结果还得从头再来。rsync的--partial参数专门解决这个问题。

它的工作机制是这样的:rsync在传输过程中会把接收到的数据写入目标位置的临时文件。如果传输中断,加上--partial之后,临时文件不会删除。下一次执行相同命令时,rsync会对比这个临时文件和源文件,找出还未传输的块继续传。

实操命令:

# 第一次传输,中断也不要紧 rsync -avz --partial --progress big_file.tar.gz root@192.168.1.100:/opt/ # 网络恢复后,重复执行同样的命令即可继续 rsync -avz --partial --progress big_file.tar.gz root@192.168.1.100:/opt/

注意我加了--progress,这个参数在传输时实时显示进度、速率和剩余时间,传大文件时能让你心里有数,不至于干等着不知道进行到哪一步了。

4.2 用screen/tmux保住长任务,SSH断开也不怕

rsync虽然能做断点续传,但有个前提:你得重新登录服务器再执行一次命令。如果连续断网、反复重传,体验仍然很差。更优雅的方案是提前用screen或tmux把rsync任务放在一个“永不中断”的会话里执行。

# 新建一个名为upload的screen会话 screen -S upload # 在screen会话里执行rsync rsync -avz --partial --progress big_file.tar.gz root@192.168.1.100:/opt/ # 按Ctrl+A,再按D,detach会话,让任务在后台继续跑 # 重新连接 screen -r upload # 查看所有会话 screen -ls

screen的核心价值在于:即使你的SSH客户端断开了,screen会话里的任务仍然在服务器上运行。这相当于把上传任务“托管”在了服务器端,本地断网不影响。

tmux用法类似,只是命令稍有不同:

# 新建会话 tmux new -s upload # 断开会话但不终止任务 # 先按Ctrl+B,再按D # 重新附着 tmux attach -t upload # 列出会话 tmux ls

这里有个经验之谈:如果你要传的文件非常大(比如几十GB),建议把--partial和screen合起来用。万一服务器重启或者任务被意外kill掉,有了--partial,下次执行rsync可以从断点继续;有了screen,可以让你不用重头敲命令。

4.3 大文件还可以先分卷再传,关键命令我直接给出

还有一种非常实用的场景:上传通道带宽有限,而且上传中断频繁。这时可以将大文件分卷压缩成多个小文件,逐卷上传,最后在服务器上合并。这个方法看起来笨,但在某些特定网络环境下比断点续传更可靠。

# 本地分卷归档,每卷200MB tar czf - big_data_dir | split -b 200M - part_ # 将part_aa、part_ab等文件按顺序上传到服务器 scp part_* root@192.168.1.100:/opt/ # 服务器上合并解压 cat part_* | tar xzf - -C /opt/

这里split命令后面的-b 200M指定每卷大小,part_是生成文件名的前缀。合并时cat part_*会按字母顺序拼接,恢复出原始归档,再用tar解压。这个方法在带宽窄、连接不稳定的场景下确实比任何断点续传方案都稳,因为单个文件小,传挂的概率低,顶多重传一个小卷。

4.4 关于并发加速:不要盲目追求多进程

有人会建议用多进程并发来加速传输,比如同时跑8个rsync。这个方法在同一个服务器和同一带宽下,效果极其有限,因为瓶颈在带宽而不是连接数。盲目开多进程反而会让服务器内存和CPU承压。

真正有效的加速路径是这些:开压缩传输(-z)减少网络传输量;换更快的网络链路;用--bwlimit限制带宽占用,避免上传任务把服务器带宽全占满影响线上业务。先把这几个做了,再考虑并发的问题。

5. 上传失败排查:从端口到权限的完整链路

5.1 一次真实的上传失败排查记录

上个月帮同事排查一个rsync上传报错,报错内容只有一行:

rsync: failed to connect to 192.168.1.100: Connection timed out (110)

很多人看到这个报错第一反应是服务器挂了,或者服务器上的SSH挂了。但如果你按下面的链路排查,很快就能定位。

第一步:看网络是否通。

ping 192.168.1.100 -c 4

ping通说明网络链路没问题,继续往下。ping不通,问题在网络层,检查IP、网关、安全组。

第二步:看SSH端口是否通。

telnet 192.168.1.100 22 # 或者用nc测试 nc -vz 192.168.1.100 22

22端口通了,说明服务器上的sshd服务在监听;不通,可能是服务器sshd没起、防火墙拦截、或者安全组没放行22端口。

那次排查的结果是22端口telnet超时。登录云控制台看安全组,确认22端口规则还在;再用网页VNC登录服务器,执行:

systemctl status sshd

输出显示sshd服务正常。继续看防火墙:

firewall-cmd --list-all # CentOS/RHEL # 或 ufw status # Ubuntu/Debian

发现问题出在firewalld把22端口过滤了,执行:

firewall-cmd --permanent --add-service=ssh firewall-cmd --reload

再测一次22端口,通了,rsync恢复正常。整个排查过程不到10分钟,但如果不按链路走,而是一次次重启sshd、重启服务器,就完全是在浪费时间。

5.2 上传到一半失败:先查磁盘和目标路径的剩余空间

还有一种非常常见的故障:上传过程中提示No space left on device或者报错内容里包含write failed。这种情况大概率是磁盘满了。

排查命令:

# 查看整体磁盘使用情况 df -h # 查看目标目录占用空间 du -sh /opt/upload_dir/ # 查看inode使用情况(小文件多时会遇到inode耗尽) df -i

注意df -i查inode这个点,很多人会漏掉。当服务器上小文件极多时,可能磁盘空间还有剩余,但inode耗尽了,同样无法写入任何新文件。

5.3 Permission denied:看懂权限位,别乱用root

上传命令执行后提示Permission denied (publickey,password)是另一类高频问题。这个提示有两层含义:要么账号密码错误,要么当前用户对目标目录没有写权限。

先确认目标目录的具体权限:

ls -ld /opt/upload_dir/ # 输出示例:drwxr-xr-x 2 root root 4096 Jan 1 00:00 /opt/upload_dir/

这个目录只有root可以写。如果我用www用户上传,就写不进去。解决方式有两种:

# 方式一:把目录所属者改为当前用户 sudo chown -R www:www /opt/upload_dir/ # 方式二:给目录增加写权限(不推荐直接777) sudo chmod -R u+rwx /opt/upload_dir/

我见过很多新手一上来就给目录chmod 777,这是最糟糕的解法。777意味着所有用户都能读写执行,等于把这个目录的门卸了。合理的做法是根据业务需要设置owner和group,再配合最小化的权限位。

5.4 SELinux也是“权限不足”的隐形元凶

在CentOS/RHEL系列系统上,还有一个容易被人忽略的因素:SELinux。你明明给了正确的用户和权限,上传也成功了,但Web服务器就是读不了文件。这时很有可能是SELinux的上下文标签不对。

# 临时关闭(不推荐,但可用于快速验证是否是SELinux问题) setenforce 0 # 如果你上传的是Web目录,给文件打上httpd_sys_content_t标签 chcon -R -t httpd_sys_content_t /var/www/html/

如果setenforce 0之后问题消失,确认就是SELinux策略导致的。不要直接永久关闭SELinux(修改/etc/selinux/config),正确做法是找出正确上下文打上标签,或者使用restorecon恢复默认上下文。

6. 上传之外的安全底线:校验、隔离与目录权限

6.1 传完不等于完事,校验文件完整性是最后一步

文件上传到服务器后,第一时间进行校验,尤其是在生产环境部署版本包。校验方法很简单,本地和服务器各算一次哈希值,对比一致说明传输过程没有损坏。

# 本地计算 sha256sum local_file.tar.gz # 服务器端计算 sha256sum /opt/uploaded_file.tar.gz

对比两边输出的哈希值,一致就放心了。如果希望更快,可以用md5sum;但md5在安全性上已经被突破,更适合快速校验而非安全场景。

有些人会把校验这一步省掉,但我的经验是:一旦文件在某次传输中损坏,部署到生产环境后排查问题的成本,远比提前花10秒校验要高得多。

6.2 别用root账号直接传文件,给业务建专属用户

很多教程里的命令都直接用root,方便是方便,但隐藏风险不小。root账号权限太高,一旦上传的脚本文件存在恶意内容,执行后就等于给了攻击者完整的系统控制权。

更合理的做法是为每个业务创建专属用户,并把上传目录的所有权赋予该用户:

# 创建运维专用用户 sudo useradd -m -s /bin/bash deploy sudo passwd deploy # 把上传目录给deploy用户 sudo mkdir -p /opt/app_upload sudo chown -R deploy:deploy /opt/app_upload sudo chmod 750 /opt/app_upload

这样上传入口隔离成独立用户,即使出现安全问题,攻击者也只能在该用户权限范围内操作。尤其多人协作时,千万不要公用一个root账号,出了问题无法定位责任人。

6.3 上传目录也要防“二次被利用”

这一点主要是给跑Web应用的读者提个醒。网站的文件上传功能在接收用户文件时,必须对上传目录做一系列加固,否则黑客上传一个恶意脚本到网站目录里,通过Web直接访问就能执行,形成经典的“文件上传漏洞”。

几条实用的防护思路:

  • 上传目录禁止执行脚本。以Nginx为例,可以关闭该目录的PHP执行权限:
location ^~ /uploads/ { location ~ \.(php|php5|sh|py)$ { deny all; } }
  • 强制重命名上传文件。上传后不要让用户控制文件名,而是由程序生成随机文件名,避免用户上传.php文件后直接用原始路径访问。
  • 校验文件内容而不只是扩展名。很多“上传后门”是用图片马等方式实现的,如果只校验扩展名很容易被绕过。更可靠的是用服务端库检测文件的真实类型(MIME、文件头)。
  • 上传目录不要放在Web根目录直接可访问的位置,如果允许,建议上传文件存储在Web根目录之外,通过程序代理访问,彻底断了脚本执行的可能。

6.4 SSH层的基本安全配置:密钥登录 + 禁止密码登录

既然上传文件基本都是走SSH通道,SSH本身的安全配置就不能松懈。最低限度的三件事:

  • 用SSH密钥对代替密码登录。本地生成密钥对后,把公钥追加到服务器的~/.ssh/authorized_keys中。
  • 确认/etc/ssh/sshd_config中允许密钥认证,并考虑关闭密码登录:
PubkeyAuthentication yes PasswordAuthentication no
  • 关闭root直接SSH登录,运维用户需要root权限时用sudo

这几项做完,基本可以防止绝大多数针对SSH的暴力破解和密码扫描。改完之后记得systemctl restart sshd,而且改配置时保持当前SSH连接不断开,以免配置错误把自己锁在外面。

几点实在的收尾建议

写到最后,分享几个我在实际项目中总结的个人习惯。

如果你的目标只是“把文件传上去”,scp最省事;如果这个动作会反复出现,rsync加部分参数是你最值得投资的工具。大文件传输前,先看一眼服务器磁盘和网络带宽,再决定用不用分卷。上传失败不要慌,按照网络通畅性、22端口、sshd状态、防火墙、磁盘空间、目录权限、SELinux这个顺序排查,基本能解决九成问题。

还有一点很重要:在正式服务器上操作前,强烈建议先在本地虚拟机里把这些命令全部跑一遍。传错文件、误删数据这种事,第一次发生最好是在自己的测试环境里,而不是在客户的机器上。把这些基础的传文件技能练熟,节省的不只是时间,还有很多不必要的折腾。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询