我正在使用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
使用CNT
和MAX_CNT
您可以禁用无限循环(如果文件successful
未传输)。 产品MAX_CNT
和SLEEP_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
本地和远程文件的校验和( md5sum
, sha256sum
, sha512sum
)会告诉你它们是否相同。
对于没有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