scp简介
scp 是 Linux 系统下基于 SSH 登陆进行安全的远程文件拷贝命令。它允许你在不同的 Linux 机器之间复制文件或目录。
使用 scp 命令的基本格式如下:
- 从本地复制到远程:
scp [options] source_file user@remote:destination_folder
- 从远程复制到本地:
scp [options] user@remote:source_file destination_folder
其中,[options] 是可选的参数,例如 -r 用于递归复制目录,-p 用于保留文件属性(如时间戳)。
例如,如果你想将本地的 file.txt 文件复制到远程服务器 192.168.1.1 的 /home/user 目录下,你可以使用以下命令:
scp file.txt user@192.168.1.1:/home/user
在执行 scp 命令时,可能需要输入远程服务器的密码。如果你希望避免输入密码,可以使用 SSH 密钥对进行身份验证。
进阶用法
既然scp可以做到【从本地复制到远程】和【从远程复制到本地】,那它是否可以实现【从远端复制到远端】呢?
答案是显而易见的
从远端复制到远端:
scp [options] user1@remote1:source_file user2@remote2:destination_folder
例如,如果你想将远程服务器 192.168.1.1 的 /file.txt 文件复制到远程服务器 192.168.1.2 的 /home/user 目录下,你可以使用以下命令:
scp user@192.168.1.1:/file.txt user@192.168.1.2:/home/user
清空问题
scp如此灵活,在使用的时候,我就遇到了很奇怪的问题——清空问题,即scp的源文件如果跟目标文件实际是一个的时候,不但没有拷贝过程,还将源文件给清空了。这就属于非常严重的问题了,下面说一下分析过程。
分析过程
- 对比测试
在测试的过程中,发现实际并不是所有的场景都会触发清空问题,再对比了环境之后,发现openssh的版本不一样。
openssh8.6 scp的源文件如果跟目标文件实际是一个的时候,不会清空文件。
openssh9.1 scp的源文件如果跟目标文件实际是一个的时候,会清空文件。
那我们首先想到的是不是不同版本ssh的配置不一样导致的问题。所以将8.6所有配置同步到9.1的环境上,测试发现问题依然存在。
- 代码分析
分析代码肯定能发现问题,但通常这一步总是最后做,究其原因还是因为阅读代码有时是个非常耗时的行为。
经过对比分析8.6和9.1的源码,我们发现了拷贝操作确实存在差异。8.6采用的是scp协议的拷贝,9.1添加了模式参数,默认采用了sftp协议的拷贝。
进一步分析
8.6与8.7源码对比来看,8.7就已经添加了模式参数,不过默认还是scp协议。
8.9与9.0源码对比来看,9.0的默认模式参数,从scp协议切到了sftp。
总结
- 8.7版本以上,添加了一个新的模式参数,默认MODE_SCP
- 9.0版本以上,模式参数从默认MODE_SCP该到了MODE_SFTP
- 9.0版本以上,如果想要scp命令不会造成清空文件的风险,需要添加一个新的参数-O
>=8.7版本
>=9.0版本:
scp -O user@192.168.1.1:/file.txt user@192.168.1.2:/home/user