RDP Monster

scp 命令详解:向 VPS 传输文件(rsync、sftp)

scp 命令详解:向 VPS 传输文件(rsync、sftp)

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 --deletescp 无法删除文件
续传大文件rsync -P 或 sftp 的 regetscp 只能从头重传
先浏览再挑选文件sftp 或 WinSCP可交互列出目录
成千上万的小文件rsync 或通过 ssh 传 tarscp 的单文件开销占主导
没有 WSL 的 WindowsPowerShell 的 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 并没有被移除,但从 OpenSSH 9.0 起它改用 SFTP 协议传输,因为原来的 scp 协议已被宣布过时。
OpenSSH 开发者认为原始的 scp/rcp 协议已经过时且难以保证安全,从 OpenSSH 9.0(2022 年)开始,scp 命令改为通过 SFTP 传输文件。命令本身、参数以及 user@host:path 语法都没有变化,现有脚本可以继续使用;只有远程路径中的 shell 展开行为不同,而 -O 可为需要的服务器恢复传统协议。对于新的自动化任务,rsync 或 sftp 功能更强,但一次性复制用 scp 完全没问题。

可以用密码而不是 SSH 密钥来使用 scp 吗?

可以,前提是服务器仍允许密码认证;scp 会像 ssh 一样提示输入密码。
scp 使用 ssh 连接该主机时所用的认证方式。如果 sshd 配置了 PasswordAuthentication yes,scp 会提示输入密码并继续复制;没有任何参数可以在命令行里传入密码,而 sshpass 之类的工具会把密码留在 shell 历史记录中。加固过的服务器通常会禁用密码登录,此时 scp 会以 Permission denied (publickey) 失败,直到你用 ssh-copy-id 部署密钥为止。脚本要无人值守运行,也必须依靠密钥。

scp 会不提示就覆盖已有文件吗?

会:scp 和 rsync 都会静默替换目标端的文件,不确定时先用 rsync --dry-run 预览。
scp 会覆盖目标端同名的任何文件,既不提示也没有跳过选项。rsync 同样会覆盖,但只在源文件不同时才动手,而且给了你控制手段:-n(--dry-run)打印将要发生的变更,--ignore-existing 保留已存在的文件不动,--update 跳过目标端更新的文件,--backup --backup-dir=DIR 保留被替换的旧版本。对于无法恢复的数据,先复制到一个全新目录,再整体切换过去。

如何在两台 VPS 服务器之间直接复制文件?

要么在其中一台服务器上运行 rsync 或 scp 指向另一台,要么用 scp -3 让数据经过你自己的机器中转。
最快的方式是服务器到服务器:ssh 登录源 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 托管、服务器管理、网络和隐私工具的指南。

注册加入我们的分销商计划

您的信息

如有任何疑问, 点击这里联系我们 !
姓名(必填)
请填写您的邮箱地址,您必须拥有以下网站的账号: dashboard.rdp.monster !

您的公司

如果您有网站,请填写网址
请简要说明您打算如何向客户销售服务,例如在论坛上与人交流推广。

连怪兽都爱吃 cookie!

我们使用 cookie 来改善您的浏览体验、提供个性化的广告或内容,并分析网站流量。点击「接受」即表示您同意我们使用 cookie。