linux scp:如何发现复制已完成

mcdcgff0  于 2023-03-17  发布在  Linux
关注(0)|答案(8)|浏览(376)

我正在使用scp命令将文件从一台Linux主机复制到另一台。我在host1上运行scp commit,然后将文件从host1复制到host2。文件相当大,复制它需要一些时间。在host2上,文件在复制开始后立即出现。即使复制仍在进行中,我也可以对该文件执行任何操作。
是否有可靠的方法来确定host2上的拷贝是否已完成?

31moq8wy

31moq8wy1#

在我的脑海里,你可以这样做:

touch tinyfile
scp bigfile tinyfile user@host:

然后,当tinyfile出现时,您知道bigfile的传输已完成。
正如注解中指出的,这里假设scp会按照指定的顺序逐个复制文件,如果你不信任它,你可以显式地逐个复制:

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

这种方法的缺点是你可能需要验证两次,如果这是一个问题,你可以使用类似ssh-agent的方法。

tyg4sfes

tyg4sfes2#

在发送端(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秒。

ncecgwcz

ncecgwcz3#

本地和远程文件的校验和(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
b4wnujal

b4wnujal4#

如果使用inotify-tools,则解决方案如下所示:

while ! inotifywait -e close $(dirname ${bigfile_fullname}) 2>/dev/null | \
    grep -Eo "CLOSE $(basename ${bigfile_fullname})$">/dev/null
do true
done
echo "File ${bigfile_fullname} closed"
i7uaboj4

i7uaboj45#

经过一番调查,以及在其他论坛上对这个问题的讨论,我又找到了一个解决办法。也许它能帮助到一些人。
有一个命令“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`
bxgwgixi

bxgwgixi6#

对于重复的问题How to check if file has been scp 100% to the remote location,这是一个expect脚本,要知道文件是否完全传输,我们可以添加expect 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
50pmv0ei

50pmv0ei7#

如果避免第二次SSH握手很重要,您可以使用类似以下的方法:

ssh host cat \> bigfile \&\& touch complete < bigfile

然后等待在远程终端上创建“完整”文件。

eimct9ow

eimct9ow8#

只需使用rsync--因为它将写入一个隐藏临时文件,然后在复制完成时重命名该文件

相关问题