scp 命令详解:向 VPS 传输文件(rsync、sftp)
- 2026年11月14日
- 09:00
- 作者: Adrien Roche
- 教程

Linux 中的 scp 命令:语法与基本传输
scp(secure copy)通过 SSH 在机器之间复制文件,因此 ssh 能用的用户名、密钥和端口,scp 同样适用。命令格式始终是 scp [options] SOURCE DESTINATION,远程一侧写成 user@host:path。它需要可用的 SSH 登录;如果 22 端口还没有响应,请先在 Ubuntu 上启用并加固 SSH。
1. 本地到远程(上传)
scp backup.tar.gz user@SERVER_IP:/home/user/
scp backup.tar.gz user@SERVER_IP:~/backups/renamed.tar.gz
scp *.conf user@SERVER_IP:~/nginx-conf/
路径以斜杠结尾时,文件会以原名放进该目录;写完整路径则会在落地时重命名。只要目标是一个目录,就可以在目标之前列出多个本地文件,而该目录必须事先存在:scp 不会创建上级目录。
2. 远程到本地(下载)
scp user@SERVER_IP:/var/log/nginx/access.log .
scp user@SERVER_IP:'/var/log/nginx/*.log' ./logs/
点号表示“放在当前目录,保持同名”。远程通配符要加引号,避免被本地 shell 展开。远程到远程也可以:scp -3 user@HOST_A:/data/dump.sql user@HOST_B:/data/ 会让数据经过你的机器中转,因此只需你本机同时拥有两台服务器的凭据。
3. 用 -r 复制目录
scp -r ./site user@SERVER_IP:/var/www/
scp -r user@SERVER_IP:/etc/nginx ./nginx-backup
-r 会复制目录及其下的全部内容。第一条命令在服务器上创建 /var/www/site;第二条把整个 nginx 目录树下载到本地文件夹。符号链接会被当作普通文件复制,这也是复制完整系统目录树时 rsync 更合适的原因之一。
真正会用到的 scp 选项:-P、-i、-C、-p
scp -P 2222 file.txt user@SERVER_IP:/home/user/ # non-default SSH port
scp -i ~/.ssh/id_ed25519 file.txt user@SERVER_IP:~/ # use a specific key
scp -C dump.sql user@SERVER_IP:~/ # compress in transit
scp -rp ./site user@SERVER_IP:/var/www/ # keep times and modes
端口参数是大写的 -P。小写 -p 表示“保留修改时间、访问时间和权限位”,而 ssh 本身用 -p 表示端口,所以混淆这两个是最常见的 scp 错误。要避免每次都重复输入端口和密钥,可以在 ~/.ssh/config 里定义一次主机;scp、rsync 和 sftp 都会读取它:
Host vps
HostName SERVER_IP
User user
Port 2222
IdentityFile ~/.ssh/id_ed25519
还有两个参数:-l 8000 把传输限制在 8,000 Kbit/s(约 1 MB/s),-v 在认证失败时显示尝试了哪些密钥。从 OpenSSH 9.0 起,scp 底层使用 SFTP 协议;语法不变,但嵌在远程路径里的 shell 技巧(例如命令替换)不再在服务器上执行,而 -O 可以为拒绝新模式的老旧服务器恢复传统协议。
rsync:镜像、可续传的传输与排除规则
rsync 只复制发生变化的内容。首次运行与 scp -r 类似;之后的运行会比较两端,只发送差异:新增文件,以及已修改文件中变动的数据块。这使它成为部署、备份和大体量传输的首选工具。两端都必须安装(sudo apt install rsync);部分精简镜像和容器默认不带它。
1. 日常命令
rsync -avz --progress ./site/ user@SERVER_IP:/var/www/site/
rsync -avz --progress user@SERVER_IP:/var/www/site/ ./site-backup/
-a(archive)等价于 -rlptgoD:递归、保留符号链接、保留权限、时间、属组、属主和设备文件;只有接收端以 root 运行时才能保留属主。-v 列出文件,-z 压缩,--progress 显示每个文件的进度。
末尾的斜杠很关键。./site/ 表示“site 目录的内容”;./site 表示“目录本身”,那样会生成 /var/www/site/site。不确定时加上 -n(--dry-run),在写入任何数据前先看一遍文件列表。
2. 用 --delete 做镜像
rsync -avzn --delete ./site/ user@SERVER_IP:/var/www/site/ # dry run first
rsync -avz --delete ./site/ user@SERVER_IP:/var/www/site/
--delete 会删除源端已不存在的目标端文件。真正的镜像需要它,但它也正是让末尾斜杠写错变成“清空目录”的原因,所以每条新的 --delete 命令都先试跑一次。
3. 排除文件
rsync -avz --exclude='node_modules/' --exclude='.git/' --exclude='*.log' ./app/ user@SERVER_IP:/srv/app/
rsync -avz --exclude-from='.rsyncignore' ./app/ user@SERVER_IP:/srv/app/
匹配模式相对于传输根目录;开头的斜杠表示锚定,因此 /config.php 只排除顶层的那个文件。--exclude-from 按每行一个模式读取规则文件。
4. 续传、自定义端口与密钥
rsync -avP -e 'ssh -p 2222 -i ~/.ssh/id_ed25519' ./disk.img user@SERVER_IP:/backup/
-P 是 --partial --progress 的简写:连接中断时会保留已传输的部分文件,重新运行同一条命令即可从断点继续。SSH 参数通过 -e 传入,这里端口用小写 -p,因为那是 ssh 的参数而不是 rsync 的;在 ~/.ssh/config 里写一条 Host 配置就能省掉整串 -e。
sftp:基于同一 SSH 登录的交互式传输
sftp 在 SSH 之上提供类似 FTP 的交互提示符,适合先浏览再复制。
sftp -P 2222 -i ~/.ssh/id_ed25519 user@SERVER_IP
sftp> ls -l /var/www
sftp> lcd ~/Downloads
sftp> get /var/log/syslog
sftp> put -r ./site /var/www/
sftp> reget backup.iso
sftp> bye
以 l 开头的命令作用于本机(lcd、lls、lpwd),其余作用于服务器。put -r 和 get -r 复制目录,reget 和 reput 续传中断的文件,!command 可以不退出会话就执行本地 shell 命令。sftp -b commands.txt user@SERVER_IP 会按文件批量重放这些命令,适合定时任务。
从 Windows 复制文件:PowerShell 的 scp 与 WinSCP
Windows 10(1809 及以后)和 Windows 11 自带 OpenSSH 客户端,因此 PowerShell 中可以直接用 scp、sftp 和 ssh,参数与 Linux 完全一致:
cd C:\Users\you\Projects
scp -P 2222 -i $HOME\.ssh\id_ed25519 .\site.zip user@SERVER_IP:/home/user/
scp -r user@SERVER_IP:/var/www/site $HOME\Downloads
密钥存放在 C:\Users\you\.ssh\,与 known_hosts 同目录,ssh-keygen -R SERVER_IP 在这里同样有效。先 cd 再用相对路径,可以避免盘符与主机名混淆。系统不含 rsync;最省事的办法是用 WSL:wsl rsync -avz /mnt/c/Users/you/site/ user@SERVER_IP:/var/www/site/。
如果想要图形界面,WinSCP 是常见选择:它支持 SFTP 和 SCP,提供双栏拖放视图,其 Synchronize 功能大致相当于 rsync --delete。它默认使用 PuTTY 的 .ppk 密钥格式,选择 OpenSSH 密钥时会提示转换。对于需要反复执行的部署,写进脚本里的一行 scp 或 rsync 更便于审阅和自动化。
scp、rsync 与 sftp:该用哪一个
| 任务 | 最佳工具 | 原因 |
|---|---|---|
| 单个文件,只传一次 | scp | 命令最短,无需安装 |
| 目录,首次复制 | scp -r 或 rsync -a | 结果等效 |
| 反复部署或备份 | rsync | 只发送变化的数据 |
| 带删除的镜像同步 | rsync --delete | scp 无法删除文件 |
| 续传大文件 | rsync -P 或 sftp 的 reget | scp 只能从头重传 |
| 先浏览再挑选文件 | sftp 或 WinSCP | 可交互列出目录 |
| 成千上万的小文件 | rsync 或通过 ssh 传 tar | scp 的单文件开销占主导 |
| 没有 WSL 的 Windows | PowerShell 的 scp 或 WinSCP | 没有原生 rsync |
经验法则:能凭记忆敲出命令时用 scp,只要会运行第二次就用 rsync。
真正有效的提速技巧
- 压缩并非免费。
-C(scp)和-z(rsync)能显著压缩文本、SQL 转储和日志,但对压缩包、图片和视频只是浪费 CPU。如果传输期间top显示sshd占满 100%,就去掉这个参数。 - 把大量小文件打包。推送源码目录时,单文件往返开销占主导;单条数据流更快:
tar czf - ./site | ssh user@SERVER_IP 'tar xzf - -C /var/www/'。 - 高速链路上换一种加密算法。当瓶颈在 ssh 进程本身时,
scp -c aes128-gcm@openssh.com会用上几乎所有现代 CPU 内置的 AES 指令。 - 保护长时间传输。把命令放进
tmux或screen里运行,会话断开也不会中断复制;或者使用rsync -P后重新运行。 - 校验与限速。两端的
sha256sum file应当一致;scp -l或rsync --bwlimit可避免备份把业务带宽吃光。
权限、属主与常见错误
目标路径 Permission denied
scp: /var/www//html/: Permission denied 表示登录成功,但该用户无权写入那里。可以先复制到自己的主目录再 sudo mv,或把目标目录的属主改为该用户(sudo chown -R user:user /var/www/site),或在 rsync 中加上 --rsync-path="sudo rsync"(当登录用户拥有免密码 sudo 时有效,配置方式见在 Linux 上创建带 sudo 权限的用户)。以 root 身份上传虽然能绕过该错误,却会留下 web 服务器无法写入的 root 属主文件:之后需要 sudo chown -R www-data:www-data /var/www/site。
Permission denied (publickey)
服务器拒绝了认证。检查用户名,用 -i 强制指定密钥,加上 -v;在 VPS 上执行 sudo journalctl -u ssh -n 30 可以看到具体原因。
Remote host identification has changed
重装系统或更换 IP 后出现这种提示是正常的:主机密钥与 ~/.ssh/known_hosts 中的记录不再匹配。如果确实重建过服务器,运行 ssh-keygen -R SERVER_IP 后重新连接。如果没有,先查清原因,别急着在任何地方输入密码。
No such file or directory
scp 不会创建上级目录:先运行 ssh user@SERVER_IP 'mkdir -p /var/www/site'。rsync 只会创建路径最后一级目录(--mkpath,rsync 3.2.3 及以上,可创建上级目录)。
rsync: command not found,或 protocol data stream(错误码 12)
有一端没有安装 rsync;在那台机器上执行 sudo apt install rsync 后重试。
上传后无法运行的脚本
来自 Windows 的文件没有可执行位,而且常带 CRLF 换行符,会导致 bad interpreter: No such file or directory。用 chmod +x deploy.sh 和 sed -i 's/\r$//' deploy.sh 同时解决这两点;shebang 相关内容参见.sh 文件是什么以及 bash 如何运行它。最后一个经典陷阱:scp file.txt user@SERVER_IP 在主机名后漏掉冒号,就变成了本地复制,会悄悄生成一个名为 user@SERVER_IP 的文件。
以上都假设你有一台能以 root 或 sudo 用户通过 SSH 访问的服务器,限制来自传输本身而不是配额。rdp.monster 的 Linux VPS 就是这样的机器:完整 root 权限、独享 CPU 与内存、无限流量(合理使用)、无需 KYC、支持加密货币付款,每月 $8.99 起,并且在付款确认后约 10 秒服务器即上线,所以你在上面运行的第一条命令就可以是第一步里的那条 scp。
常见问题
scp 命令被废弃了吗?
scp 命令改为通过 SFTP 传输文件。命令本身、参数以及 user@host:path 语法都没有变化,现有脚本可以继续使用;只有远程路径中的 shell 展开行为不同,而 -O 可为需要的服务器恢复传统协议。对于新的自动化任务,rsync 或 sftp 功能更强,但一次性复制用 scp 完全没问题。可以用密码而不是 SSH 密钥来使用 scp 吗?
PasswordAuthentication yes,scp 会提示输入密码并继续复制;没有任何参数可以在命令行里传入密码,而 sshpass 之类的工具会把密码留在 shell 历史记录中。加固过的服务器通常会禁用密码登录,此时 scp 会以 Permission denied (publickey) 失败,直到你用 ssh-copy-id 部署密钥为止。脚本要无人值守运行,也必须依靠密钥。scp 会不提示就覆盖已有文件吗?
-n(--dry-run)打印将要发生的变更,--ignore-existing 保留已存在的文件不动,--update 跳过目标端更新的文件,--backup --backup-dir=DIR 保留被替换的旧版本。对于无法恢复的数据,先复制到一个全新目录,再整体切换过去。如何在两台 VPS 服务器之间直接复制文件?
rsync -avz /data/ user@OTHER_IP:/data/(或 scp -r),数据完全不经过你的家庭网络。这要求第一台服务器持有第二台接受的密钥。如果你不愿把密钥放在服务器上,scp -3 user@HOST_A:/path user@HOST_B:/path 会仅用本地凭据经你的机器中转,代价是所有数据都要各下载和上传一次。Adrien Roche, 基础设施与主机托管编辑
系统工程师,拥有 10 年以上运维 Windows Server 和 Linux 集群的经验。Adrien 负责 rdp.monster 的基础设施文档,并撰写关于 RDP、VPS 托管、服务器管理、网络和隐私工具的指南。




