scp:如何找出复制完成

我正在使用scp命令将文件从一台Linux主机复制到另一台主机。 我在主机1上运行scp命令,并从主机1复制文件到主机2。 文件相当大,复制它需要一段时间。 一旦复制开始,host2文件立即出现。 即使正在进行复制,我也可以用这个文件做所有事情。

有没有可靠的方法来确定复制是否完成或不在host2上?

在我头顶上,你可以做一些事情:

touch tinyfile scp bigfile tinyfile user@host: 

然后当tinyfile出现时,你知道tinyfile的传输是完整的。

正如在评论中指出的那样,这个假定scp会按照指定的顺序一个接一个地复制文件。 如果你不信任它,你可以一个一个明确地做:

 scp bigfile user@host: scp tinyfile user@host: 

这种方法的缺点是,你可能不得不认证两次。 如果这是一个问题,你可以使用类似ssh-agent的东西。

在发送方(host1)使用这样的脚本:

 #!/bin/bash echo 'starting transfer' scp FILE USER@DST_SERVER:DST_PATH OUT=$? if [ $OUT = 0 ]; then echo 'transfer successful' touch successful scp successful USER@DST_SERVER:DST_PATH else echo 'transfer faild' fi 

在接收端(host2)使脚本如下所示:

 #!/bin/bash SLEEP_TIME=30 MAX_CNT=10 CNT=0 while [[ ! -e successful && $CNT < $MAX_CNT ]]; do ((CNT++)) sleep($SLEEP_TIME); done; if [[ -e successful ]]; then echo 'successful' rm successful # do somethning with FILE fi 

使用CNTMAX_CNT您可以禁用无限循环(如果文件successful未传输)。 产品MAX_CNTSLEEP_TIME应等于或大于预期的传输时间。 在我的例子中,预期的传输时间少于300秒。

经过一番调查,并在其他论坛上讨论这个问题,我又找到了一个解决方案。 也许它可以帮助别人。

有一个命令“lsof”。 它列出了打开的文件。 在复制过程中,文件将被打开,所以命令

lsof | grep filename

将返回非空结果。

所以你可能想做一个while循环等到lsof不返回任何东西,然后继续执行你的任务。

例如

 # provide your file name here f=<nameOfYourFile> lsofresult=`lsof | grep $f | wc -l` while [ $lsofresult != 0 ]; do echo still copying file $f... sleep 5 lsofresult=`lsof | grep $f | wc -l` done; echo copying file $f is finished: `ls $f` 

对于重复的问题, 如何检查文件是否已经远程位置scp 100% ,这是一个期望的脚本,知道一个文件是否完全传输,我们可以添加期望100%.. ..即类似这样的东西…

 expect -c " set timeout 1 spawn scp user@$REMOTE_IP:/tmp/my.file user@$HOST_IP:/home/. expect yes/no { send yes\r ; exp_continue } expect password: { send $SCP_PASSWORD\r } expect 100% sleep 1 exit " if [ -f "/home/my.file" ]; then echo "Success" fi 

本地和远程文件的校验和( md5sumsha256sumsha512sum )会告诉你它们是否相同。

对于没有SSH访问远程系统的情况(比如FTP服务器),您可以在上传文件后下载并比较校验和。 我为从工作中的生产脚本发送的文件执行此操作。 下面是我在这个脚本中的一个片段。

 MD5SRC=$(md5sum $LOCALFILE | cut -c 1-32) MD5TESTFILE=$(mktemp -p /ramdisk) curl \ -o $MD5TESTFILE \ -sS \ -u $FTPUSER:$FTPPASS \ ftp://$FTPHOST/$REMOTEFILE MD5DST=$(md5sum $MD5TESTFILE | cut -c 1-32) if [ "$MD5SRC" == "$MD5DST" ] then echo "+Local and Remote files match!" else echo "-Local and Remote files don't match" fi