shell 流下载非常大的文件通过坏连接

9q78igpj  于 12个月前  发布在  Shell
关注(0)|答案(1)|浏览(130)

我想处理一个非常大的文件(几TB)作为流。此文件可通过http协议和URL访问,例如:
http://example.com/some-file
这个命令可以做到这一点:

wget -q -O - http://some-host/some-file | process-command

但如果连接丢失,我必须开始从头开始这个过程。
wget -c不能使用,因为我不能存储的文件,由于大尺寸。
是否有另一个命令可以流式传输远程文件,同时在内部处理所需的重新连接?

n6lpvg4x

n6lpvg4x1#

解决这个问题的主要思想是逐块下载文件,并将最后下载的块的偏移量写入某处。为此,首先,我们指定块大小。
块大小接近下载文件的大小,性能更好,但在连接损坏中丢失更多数据的风险增加。我的建议是下载文件大小的10%左右。根据我的经验,使用这种方法,下载速度下降了大约25 %。

#!/bin/bash

URL="Your-URL"

content_length=$(curl -I $URL | grep -i 'Content-Length' | awk '{print $2}' | tr -d '\r')

# In Bytes
chunk_size=10000000

while true; do
        offset=$(cat offset.txt | grep -Eo '[0-9]+')
        next_chunk=$((offset + chunk_size - 1))
        if [[ next_chunk -ge content_length ]]
        then
                curl -r $offset-$content_length --retry 10000 $URL > downloaded-chunk
                # In here you can do your process with the last downloaded chunk
                break
        fi
        curl -r $offset-$next_chunk $URL > downloaded-chunk
        # In here you can do your process with a downloaded chunk
        offset=$((next_chunk + 1))
        echo "Offset of the last chunk downloaded: $offset bytes"
        echo $offset > offset.txt
done

整个文件的大小需要知道我们应该在哪里使用curl和范围选项-r。最后一个数据块通常不适合块大小,这由while中的if条件处理。

相关问题