资讯动态

SCP命令详解:基于SSH的Linux安全文件传输与排错指南

发布时间:2026/10/21 2:49:44 来源:尧图企业网站定制
平时远程登录 Linux 服务器最烦的一件小事就是“文件怎么拷回来”。明明 SSH 已经连上了却只能看着远程机器上的日志、备份包、配置文件干瞪眼。要么打开浏览器走网盘要么临时装个 FTP还得开端口、配权限折腾一圈比干活还累。其实命令行里早就内置了答案SSH 远程连接之后的 scp 命令工具就是专门干这个的。scp 全称 Secure Copy走的是 SSH 协议的安全通道不需要额外开任何服务只要你能 SSH 登上去就一定能用 scp 传文件。这篇文章适合刚上手 Linux 服务器的新手也适合日常需要在本地和远端之间反复搬运文件的后端、运维还有那些到现在还靠 U 盘拷配置的人。我会从最基础的语法讲起再带你把上传、下载、目录传输、限速、断点续传这些场景全部过一遍最后把权限、连接、中断这些高频坑一次性讲清楚。1. 为什么有了 SSH还需要单独学一个 scp1.1 先搞明白 SSH 和 scp 到底什么关系很多人第一次听到 scp 的时候会困惑SSH 不是已经能远程执行命令了吗cat看一眼文件、vim改一下配置、tar打包备份好像都能做。那为什么还要单独记一套 scp 语法这么想确实有道理。SSH 本身是一个加密网络协议它建立一条安全通道让你可以在远程机器上执行命令、登录会话。但它的主要用途是“交互式的终端操作”而不是“文件数据的高效搬运”。你在 SSH 会话里用cat file EOF这种方式写文件遇到二进制文件基本就是灾难用base64编码再回显数据量小的时候还能凑合几个 GB 的备份包根本没法这么干。scp 是 SSH 协议家族里一个独立的文件传输工具它复用 SSH 的认证、加密、连接机制但专注于把文件从一个节点复制到另一个节点。你可以把它理解成SSH 是一条加密隧道这条隧道既可以走人交互式登录也可以走货scp 传文件。两者共享同一套账号密码、同一套端口、同一套密钥连权限模型都是一样的。1.2 scp 的底层传输机制为什么它“零部署”scp 最大的优势就是零部署。服务器上不需要启动任何新的守护进程不需要安装 vsftpd、Samba、NFS更不需要在云厂商的安全组里额外放行 21、445 这些端口。原因是 scp 在传输时通过 SSH 通道在远端启动一个scp进程两个 scp 进程之间通过 SSH 加密隧道直接传送数据。数据流是本地 scp 读取文件 - 加密 - SSH 隧道 - 远端 sshd 解密还原 - 交给远端 scp 进程写入磁盘。整个过程只依赖 SSH 服务默认端口 22而 SSH 服务在绝大多数 Linux 服务器上都是预装且默认开启的。所以就出现了一个很实用的场景你在一台新拿到手的云服务器上只需要确认自己能 SSH 登录就可以立刻用 scp 传文件不用再为“传文件到底用什么工具”纠结。这也是为什么我到现在还是把 scp 当成文件传输兜底方案它的可靠性和普适性几乎没有短板。2. scp 命令的核心语法与参数拆解2.1 一句话命令的三段式结构scp 的语法可以压缩成一句话scp [参数] 源路径 目标路径。和cp命令非常像区别在于路径里可以带上远程主机信息。远程路径的写法是固定的用户名主机地址:路径。注意中间有个冒号这个冒号是 scp 区分本地路径和远程路径的标识。第一次用的时候很容易漏掉它漏掉的后果就是 scp 会把整个字符串当成一个本地文件名处理然后报No such file or directory。先看三个最典型的例子# 把本地文件上传到远程服务器 scp ./backup.tar.gz root192.168.1.100:/root/ # 把远程文件下载到本地当前目录 scp root192.168.1.100:/root/log.txt ./ # 把本地目录整个复制到远程 scp -r ./data/ root192.168.1.100:/root/data/从哪个方向传关键就看远程路径写在左边还是右边。远程路径放左边就是下载放右边就是上传这个方向感和cp完全一致——源在前目标在后。路径拼接的时候要注意远程路径如果写到目录级别scp 默认会保留文件名如果写到完整的文件路径则会重命名。比如scp file.txt userhost:/tmp/会把文件放到 /tmp 目录下且名字仍叫 file.txt而scp file.txt userhost:/tmp/newname.txt就会改名。实际操作中我建议你在写命令前先把源和目标都确认一遍尤其注意本地当前目录是哪里。我见过太多人明明想下载却因为当前目录不对文件下载到了别的地方找了半天。2.2 高频参数逐个拆解大 P、小 p、-r、-C、-i、-lscp 的参数不算多但有几个长得很像、作用完全不同的必须单独拎出来说清楚。-P大写指定远程 SSH 端口。服务器如果改了默认端口比如换成了 2222不加这个参数会默认连接 22 端口直接报Connection refused。这个参数必须写在命令前面和 ssh 的习惯一致。-p小写保留文件的修改时间和访问时间。很多场景下我们需要保留原始时间戳比如备份日志、同步配置时加上小 p 可以让远端文件的 mtime 和源文件一致否则默认情况下文件的修改时间会变成传输时刻的时间。这两个参数一个是端口、一个是权限属性完全两码事新手最容易混。-r递归复制目录。如果源路径是一个目录不加-r会直接报错Not a regular file。传目录就带上它只传单个文件不需要。-C启用压缩传输。对于纯文本文件日志、配置文件、代码压缩率很高网络传输量能减少一半以上。但对于已经压缩过的文件tar.gz、zip、jpg再加一层压缩纯粹是浪费 CPU不建议开。-i指定私钥文件。服务器如果只配置了密钥登录那么 scp 的时候也要带上对应的私钥路径比如scp -i ~/.ssh/id_rsa file.txt userhost:/tmp/。-l小写 L限制带宽单位是 Kbit/s。比如scp -l 8000 file.txt userhost:/tmp/表示限制带宽为 8000 Kbit/s也就是约 1 MB/s。这个参数我在生产环境用得很多白天迁数据不想把业务带宽占满的时候限个速大家相安无事。另外还有一个-v调试模式连接出问题的时候用它看详细输出能定位到认证失败还是网络不通。平时不用加日志太啰嗦。2.3 容易踩的细节端口、权限、路径写法的记忆锚点这里我想分享几个记忆方法帮你把最容易记混的几个点一次性钉死。大小 P 的区分大写 P 是 Port端口。小写 p 是 preserve保留属性。英文单词首字母对应含义这样永远都不会忘。-r和递归下载的关联r 就是 recursive看到目录就条件反射加上它。传目录之前先看一眼路径是不是以/结尾这个符号本身就暗示了“这是一个目录”。远程路径格式userhost:path可以拆成三部分记忆user 是你用什么身份登录host 是去哪里path 是文件落在哪个位置。其中任意一部分错了scp 都会给出一个让人摸不着头脑的报错。建议养成习惯先在本地ls看一眼源文件是否存在再用ssh userhost ls -l 目标路径确认目标位置可写最后再执行 scp。多花十秒钟能少踩一半的坑。3. 实战从登录到搬运文件的完整流程3.1 场景一上传本地文件到远程服务器假设我现在要把本地一个打包好的站点目录传到服务器上部署。身体力行一次完整流程。第一步先确认本地文件和目标服务器状态。我的本地文件是这个ls -lh /tmp/site_backup.tar.gz # -rw-r--r-- 1 user user 1.2G Jul 12 10:30 /tmp/site_backup.tar.gz第二步登录远端服务器确认目录可写。这一步看起来多余但能避免传了一半才发现权限不够的尴尬ssh root192.168.1.100 mkdir -p /var/www/site df -h /var/www顺便看一眼磁盘剩多少空间。传几个 G 的大文件最怕的就是远端磁盘满了传完才发现写不进去浪费时间。第三步执行 scp 上传。服务器 SSH 端口是默认 22文件是一个 tar.gz 包本身已经被压缩过所以不加-Cscp /tmp/site_backup.tar.gz root192.168.1.100:/var/www/site/执行后会提示输入密码输入正确后开始传输。没有进度条是正常的scp 默认只在传输结束时输出速度和时间统计。看到一个100%的进度信息之后可以再 SSH 登录确认文件大小和本地一致ssh root192.168.1.100 ls -lh /var/www/site/全程就是这三步干净利落。上传文件和登录服务器其实是一样的底层逻辑所以如果 SSH 登录要输密钥、要指定端口scp 也要带同样参数这一点是相通的。3.2 场景二从远程服务器下载文件到本地下载和上传是镜像操作把远程路径放到左边就行。还是以刚才那台机器为例我想把服务器上最新的应用日志拉回本地分析scp root192.168.1.100:/var/log/app/access.log ./这里的./是本地当前目录下载完成后文件就会出现在当前终端所在的目录下。注意下载命令执行前最好先确认一下本地目录的可用空间大文件下载时如果本地磁盘满了一样会中断。如果远程日志文件分布在一个目录里想整个拉回来加上-rscp -r root192.168.1.100:/var/log/app/ ./app-logs/这里有个细节值得注意远程路径/var/log/app/末尾的斜杠表示传整个目录本地目标如果是一个不存在的目录scp 会自动创建。我建议本地目标写一个明确的目录名不要图省事直接写./否则一批文件散落在当前目录下后续整理起来很痛苦。下载方向我再补一句如果远程文件有中文名或者空格一定要用引号把整个远程路径包起来比如scp root192.168.1.100:/tmp/我的文件.tar.gz ./。否则 Shell 会把空格当成参数分隔符命令直接断掉报错找半天都想不到是这个原因。3.3 场景三跨服务器直接传输中间不落地scp 还支持两个远程服务器之间的直接传输。在没有中转工具的情况下这个功能非常实用它不需要你把文件先下载到本地再上传到另一台机器而是由本地 scp 命令调度两台远程服务器直接通信。语法很简单两边都写成远程路径格式scp root192.168.1.100:/data/file.tar.gz root192.168.1.101:/data/执行时需要输入两台服务器各自的密码或者配置好密钥认证后免密执行。传输的流量会经过本地这台机器中转所以本地网络带宽会成为瓶颈。如果两个服务器都在同一个机房走这个方式可能比下载再上传更慢此时我更推荐直接在源服务器上执行scp 目标服务器路径能省掉本地的中转开销。实际用的时候优先考虑数据流向是否合理别生搬硬套。3.4 进阶组合限速、压缩、指定私钥的杂合用法真实环境里很少只用一个参数。我整理几条高频组合用法都是踩过坑后沉淀下来的。场景一生产环境白天传输大文件怕影响业务限速加断点保护scp -l 10000 -C ./app_logs.tar.gz user192.168.1.100:/backup/-l 10000表示限速 10 Mbit/s 左右加上-C压缩实际传输的是压缩后的数据流有效吞吐能比网速上限高不少。注意-l的单位是 Kbit/s不是 KB/s10000 Kbit/s 约等于 1.2 MB/s这个牵涉到单位换算不要搞错。场景二服务器只配置了密钥登录必须指定密钥scp -i ~/.ssh/id_ed25519 -P 2222 ./config.yaml admin192.168.1.100:/etc/app/这里的-i指向私钥文件-P 2222指定 SSH 端口。场景三登录服务器需要跳板机。scp 自身不支持跳板但可以通过-o参数借用 SSH 的 ProxyJump 配置scp -o ProxyJump user跳板机IP ./file.txt user目标IP:/tmp/这个用法相当于让 scp 先通过 SSH 连上跳板机再由跳板机转发到目标服务器。对于只有内网地址、需要跳板才能访问的机器这是最省事的方案不需要额外装任何工具。4. 高频报错与排查思路实录4.1 连接相关的报错怎么定位ssh: connect to host ... port 22: Connection refused是出现频率最高的报错。看到这个报错第一反应不是去查 scp而是先在本地检查目标机器的 SSH 服务是否在运行。可以执行systemctl status sshdCentOS 系或者systemctl status sshUbuntu 系确认服务是 active 状态。第二件要排查的是端口目标机器如果改过端口scp 默认还是连 22必须加-P 指定端口。还有一种常见情况是Connection timed out这意味着网络层面的路由不通。多半是防火墙拦截了 SSH 端口或者目标主机处于内网/离线状态。排查思路是先在本地ping一下目标 IP通了再继续然后用nc -vz 目标IP 端口测试端口连通性比如nc -vz 192.168.1.100 22。如果 nc 没有安装用telnet 192.168.1.100 22也可以出现了 SSH 版本字符串说明端口是通的。4.2 Permission denied 类报错与解决套路Permission denied (publickey,password)这个报错说明认证阶段就没过。常见原因有三个密码输错、密钥不对、服务器只允许密钥登录。逐个排查很简单先用 ssh 登录一次目标机器如果 ssh 能登上去scp 也一样能登上去。问题多半出在命令参数上——比如忘了-i指定私钥或端口写错。认证通过后还会遇到一类权限报错比如scp: /target/path/file: Permission denied。这是目标目录没有写入权限。解决方式是在服务器上确认目标目录归属ls -ld /target/path看属主和权限位。如果是 root 权限登录基本不存在写权限问题如果是普通用户就需要先sudo mkdir -p并sudo chown把目录授权给当前用户。我建议传文件之前先把这个前置条件确认好否则传了一半看到报错还要重新传一遍浪费时间。4.3 大文件传输中断scp 到底能不能续传scp 最尴尬的短板就是不支持断点续传。传一个 10 GB 的文件到了 90% 突然网络抖动断开只能从头再来。这点和 rsync 相比是硬伤。如果是大文件高频传输场景我更建议直接使用 rsync它支持断点续传、增量同步还能在中断后继续传rsync -avz --partial ./bigfile.tar.gz user192.168.1.100:/backup/--partial参数的作用是保留已传输的部分文件下次执行 rsync 时只补传剩余部分。这个对网络不稳定、文件特别大的场景非常管用。如果项目环境里没有 rsync或者目标服务器不允许安装额外软件那退回 scp 就只能自己想办法。一个土办法是把大文件先切分成小份再传比如用split按大小切包split -b 500M ./bigfile.tar.gz ./part_ scp part_* user192.168.1.100:/backup/传完在远端用cat part_* bigfile_restored.tar.gz合并。这个办法不优雅但在应急场景下是真的能救命的。4.4 Windows 下用 scp 要注意的几个点Windows 环境现在已经原生支持 scp 客户端PowerShell 或 CMD 里面直接用就行。不过和 Linux 终端使用相比有几个细节需要注意。第一Windows 本地路径的写法。执行scp userhost:/data/file.txt D:\backup\这样带反斜杠的路径scp 有时会解析出问题。更稳妥的做法是把目标目录先cd进去然后用.作为目标例如cd D:\backup scp user192.168.1.100:/data/file.txt .第二Windows 自带的 OpenSSH 版本较老某些高级参数可能不支持。比如ProxyJump在部分旧版本上无法解析遇到跳板机场景会报错。解决办法是安装一个较新的 OpenSSH for Windows 版本或者直接用终端工具内置的 SFTP 功能替代——毕竟 SFTP 和 scp 同属 SSH 协议族用法也几乎相同。第三路径里如果有空格Windows 下同样用双引号包住。但要注意引号里如果有反斜杠很容易被转义建议统一把路径改成正斜杠分隔比如scp userhost:/data/my files/data.tar.gz ./。4.5 传输速度极慢是网速的问题还是命令的问题很多人遇到 scp 传大文件速度上不去第一个念头是带宽不够但实际排查下来很多时候是传输方式和服务器配置的问题。先看是不是没加压缩。文本、日志、代码这类文件加-C后的速度能提升一倍以上。如果传输的是已经压缩过的 tar.gz 包基本就没什么优化空间了。再看是不是网卡协商速率的问题有些虚拟化平台默认虚拟网卡速度较低这个可以通过ethtool eth0查看。还有一个容易被忽略的是磁盘写入速度。目标服务器的磁盘如果负载很高比如正在跑数据库备份、大量日志写入scp 的写入速度会明显下降。这种情况等磁盘负载降下来再传或者换个目录落盘。最后提一下如果本地到服务器链路质量不佳加上-o ServerAliveInterval30这个参数可以让连接保持活跃避免因为链路静默一段时间被设备掐断。5. 我的实操经验与收尾分享5.1 和 sftp、rsync 的取舍建议用了这么多年我的结论很稳定scp 适合零门槛、零部署的临时文件搬运尤其适合一两台机器之间的偶尔传输。如果你传输文件特别频繁、数据量特别大、网络又不稳定那么 rsync 是更好的选择它的增量同步、断点续传、校验机制都远比 scp 完整。而在 Windows、手机终端等场景下SFTP 因为支持文件列表浏览、拖拽上传体验上比 scp 更友好。5.2 我自己踩过的一个坑有一次我在一台服务器上 scp 下载一个日志文件命令执行后一直卡住不动。排查了很久才发现是因为远程机器的~/.bashrc里有一段欢迎信息脚本在 scp 建立通道时执行了交互式输出把传输通道给污染了。这在 scp 里其实是一个经典陷阱远端 shell 的非标准输出会干扰 scp 的数据流。解决方式是检查远端用户的 shell 配置把非必要的输出清理掉或者直接用/bin/sh作为远端 shell 运行 scp。这个案例让我明白一个道理scp 本身很可靠但远端环境的“杂音”却可能把它搞挂。遇到奇奇怪怪的 scp 行为优先复盘目标机器的 shell 配置和环境初始化脚本。方向对了问题就好解决得多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑