诡异的scp导致文件被清空问题

发布于:2024-04-29 ⋅ 阅读:(33) ⋅ 点赞:(0)

scp简介

scp 是 Linux 系统下基于 SSH 登陆进行安全的远程文件拷贝命令。它允许你在不同的 Linux 机器之间复制文件或目录。

使用 scp 命令的基本格式如下:

  1. 从本地复制到远程:
scp [options] source_file user@remote:destination_folder
  1. 从远程复制到本地:
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的源文件如果跟目标文件实际是一个的时候,不但没有拷贝过程,还将源文件给清空了。这就属于非常严重的问题了,下面说一下分析过程。

分析过程

  1. 对比测试

在测试的过程中,发现实际并不是所有的场景都会触发清空问题,再对比了环境之后,发现openssh的版本不一样。

openssh8.6 scp的源文件如果跟目标文件实际是一个的时候,不会清空文件。

openssh9.1 scp的源文件如果跟目标文件实际是一个的时候,会清空文件。

那我们首先想到的是不是不同版本ssh的配置不一样导致的问题。所以将8.6所有配置同步到9.1的环境上,测试发现问题依然存在。

  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。

总结

  1. 8.7版本以上,添加了一个新的模式参数,默认MODE_SCP
  2. 9.0版本以上,模式参数从默认MODE_SCP该到了MODE_SFTP
  3. 9.0版本以上,如果想要scp命令不会造成清空文件的风险,需要添加一个新的参数-O

>=8.7版本

>=9.0版本:

scp -O user@192.168.1.1:/file.txt user@192.168.1.2:/home/user