【问题标题】:scp: how to find out that copying was finishedscp:如何知道复制是否完成
【发布时间】:2014-05-08 22:35:30
【问题描述】:

我正在使用 scp 命令将文件从一台 Linux 主机复制到另一台。 我在主机 1 上运行 scp 推荐并将文件从主机 1 复制到主机 2。文件很大,复制它需要一些时间。 复制开始后,host2 上的文件立即出现。即使复制仍在进行中,我也可以使用此文件执行所有操作。

有没有可靠的方法来确定主机2上的复制是否完成?

【问题讨论】:

    标签: linux bash shell sh scp


    【解决方案1】:

    如果您使用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"
    

    【讨论】:

    • 欢迎来到 StackOverflow。一些解释将大大提高答案的质量,并帮助将来可能遇到类似问题的其他用户请花一些时间阅读帮助页面stackoverflow.com/help/how-to-answer
    • 我赞成这个,因为它是一个很好的答案,而且几乎不言自明,谢谢@molokovskikh
    【解决方案2】:

    如果避免第二次 SSH 握手很重要,您可以使用以下内容:

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

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

    【讨论】:

      【解决方案3】:

      经过一些调查,以及在其他论坛上对该问题的讨论,我找到了另一种解决方案。也许它可以帮助某人。

      有一个命令“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`
      

      【讨论】:

      • lsof 将查询所有进程以查找打开的文件。为什么不直接使用fuser检查文件? fuser file 将打印打开了file 的PID,如果进程是ssh,那么它仍在被复制。既不能依赖lsof 也不能依赖fuser,因为即使被中断,ssh 也会使文件保持原样。唯一可靠的方法是在文件关闭后获取校验和。在您的问题中,您说的是“可靠的方式”。
      【解决方案4】:

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

      对于您无法通过 SSH 访问远程系统(例如 FTP 服务器)的情况,您可以在文件上传后下载文件并比较校验和。我为工作中从生产脚本发送的文件执行此操作。下面是我执行此操作的脚本中的 sn-p。

      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
      

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

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

          【讨论】:

            【解决方案7】:

            在我的脑海中,您可以执行以下操作:

            touch tinyfile
            scp bigfile tinyfile user@host:
            

            那么当tinyfile出现时你就知道bigfile的传输完成了。

            正如 cmets 中所指出的,这假定 scp 将按照指定的顺序一个一个地复制文件。如果您不信任它,您可以明确地一一进行:

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

            这种方法的缺点是您可能需要进行两次身份验证。如果这是一个问题,您可以使用 ssh-agent 之类的内容。

            【讨论】:

            • 除非scp 决定一次可以复制多个文件。
            • @J.F.Sebastian 我想这是可能的,我已经相应地编辑了我的答案
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-09-12
            • 2020-02-06
            • 1970-01-01
            • 2010-10-08
            相关资源
            最近更新 更多