【问题标题】:Does AWS CLI upload files larger than 4GB to Amazon Glacier?AWS CLI 是否将大于 4GB 的文件上传到 Amazon Glacier?
【发布时间】:2018-01-21 18:45:24
【问题描述】:

AWS 命令​​行界面 (CLI) 允许 to upload a file to AWS Glacier。但在 AWS Rest API 中也有一个 limit of 4GB for file uploads。如果我需要通过 Rest API 上传大于 4GB 的文件,我需要使用分段上传。

我的问题是:AWS CLI 是否在内部处理大于 4GB 的文件上传,或者在处理大于 4GB 的文件时我是否需要自己处理分段上传?我可以将一个 20Gb 的文件传递给 AWS CLI 的 upload-archive 选项,它就可以工作吗?如果 CLI 不能直接处理大文件上传,有什么命令行工具可以帮我完成(让我免于在部分上传失败时实现所有校验和计算、错误处理和重试逻辑)?

我了解 AWS Rest API 有 4GB 限制,但我找不到任何关于如何在 CLI 中处理此限制的信息。我可以做测试,但我的上传速度不是那么快,我担心会浪费几个小时才发现它不起作用。

【问题讨论】:

  • 从 EBS 和 S3 之间的练习来看,CLI 需要明确地处理多部分上传——但这并不难
  • 根据您链接到的 cli 文档,您仍然需要自己进行树哈希计算。除非您特别需要仅 Glacier 的功能,例如保险库锁,否则上传到 S3 并使用生命周期策略迁移到 S3 Glacier 存储类可能最能满足您的兴趣。它比直接使用 glacier 更容易使用,并且存储成本基本相同(使用 S3 时每个对象开销 +40KiB)。
  • 根据S3 pricing page,在 S3 上存储对象的价格是在 Glacier 上存储价格的 5.75 倍,这让我无法在 S3 上存储对象。
  • 虽然实现分段上传并不难,但我正在寻找一个可以使用、已经过测试的命令行工具。
  • 这里还有另一个命令行工具来协调分段上传:github.com/numblr/glaciertools。它是一个围绕 aws-cli 构建的纯 bash 脚本。

标签: amazon-web-services aws-cli amazon-glacier


【解决方案1】:

我正在使用 glacier-cmd (https://github.com/uskudnik/amazon-glacier-cmd-interface),效果很好,但最近似乎不受支持。有时它会因大文件(~50GB)而超时。

【讨论】:

  • 感谢您分享此工具。 “大文件超时”是指无法上传大文件吗?还是上传需要很长时间?
  • 我查看了我的日志和 Glacier 清单 - 根据他们的说法,超时错误不会影响上传。似乎最新版本的 glacier-cmd 知道在这种情况下重试。但高达 20% 的大(50G)文件上传失败,但有一些例外。类似于这里讨论的github.com/uskudnik/amazon-glacier-cmd-interface/issues/188。底线 - AFAIK,glacier-cmd 是 AWS Glacier CLI 的唯一高级包装器,它主要工作。您可以通过一些简单的脚本来组织重试。
【解决方案2】:

下面的脚本可以正常工作。我已经为树哈希计算和文件部分单独上传创建了块。它工作得很好。

#!/bin/bash

date1=$(date +"%s")

byteSize=1073741824

CHUNK_SIZE=1073741824

hashsize=1048576

if [[ -z "${1}" ]]; then
    echo "No file provided."
    exit 1
fi

ARCHIVE="/mnt/dbfiles/mahipal/splitfiles/${1}"
ARCHIVE_SIZE=`cat "${ARCHIVE}" | wc --bytes`

cd /mnt/dbfiles/mahipal/splitfiles

rm -rf TEMP

rm -rf HASH

mkdir TEMP

mkdir HASH

cd /mnt/dbfiles/mahipal/splitfiles/TEMP

date3=$(date +"%s")

split -d --bytes=${CHUNK_SIZE} "${ARCHIVE}" chunk  -a 4

date4=$(date +"%s")

diff2=$(($date4-$date3))

cd /mnt/dbfiles/mahipal/splitfiles/HASH 

date5=$(date +"%s")

split -d --bytes=${hashsize} "${ARCHIVE}" chunk  -a 5

date6=$(date +"%s")

diff3=$(($date6-$date5))

cd /mnt/dbfiles/mahipal/splitfiles/TEMP

lastpartsize=`expr $(ls -l | tail -1 | awk '{print$5}') + 0`

lastfile=$(ls -l | tail -1 | awk '{print$9}')

cont=$(ls -l | wc -l)
cnt=`expr $cont - 2`

fileCount=$(ls -1 | grep "^chunk" | wc -l)
echo "Total parts to upload: " $fileCount

files=$(ls | grep "^chunk")

init=$(/bin/aws glacier initiate-multipart-upload --account-id - --part-size $byteSize --vault-name final_vault --archive-description "${1}_${ARCHIVE_SIZE}_${byteSize}")

echo "---------------------------------------"


uploadId=$(echo $init | jq '.uploadId' | xargs)

touch commands.txt

i=0
for f in $files 
  do
     byteStart=$((i*byteSize))
     byteEnd=$((i*byteSize+byteSize-1))
     echo /bin/aws glacier upload-multipart-part --body $f --range "'"'bytes '"$byteStart"'-'"$byteEnd"'/*'"'" --account-id - --vault-name final_vault --upload-id $uploadId >> commands.txt
     i=$(($i+1))

    if [ "$i" == "$cnt" ]
        then
    byteEnd=`expr $byteEnd + 1`
    byteEnd2=$((i*byteSize+lastpartsize-1))
    byteSize=$lastpartsize 
     echo /bin/aws glacier upload-multipart-part --body $lastfile --range "'"'bytes '"$byteEnd"'-'"$byteEnd2"'/*'"'" --account-id - --vault-name final_vault --upload-id $uploadId >> commands.txt
    break   
    fi      

  done

parallel --load 100% -a commands.txt --no-notice --bar

cd /mnt/dbfiles/mahipal/splitfiles/HASH

files=$(ls | grep "^chunk")

for f in $files
  do
     openssl dgst -sha256 -binary ${f} > "hash${f:5}"

  done


echo "List Active Multipart Uploads:"
echo "Verify that a connection is open:"

/bin/aws glacier list-multipart-uploads --account-id - --vault-name final_vault >> /mnt/dbfiles/mahipal/splitfiles/TEMP/commands.txt

echo "-------------"
echo "Contents of commands.txt"

cd /mnt/dbfiles/mahipal/splitfiles/TEMP

cat commands.txt

# Calculate tree hash.

cd /mnt/dbfiles/mahipal/splitfiles/HASH

echo "Calculating tree hash..."
while true; do
    COUNT=`ls hash* | wc -l`
    if [[ ${COUNT} -le 2 ]]; then
        TREE_HASH=$(cat hash* | openssl dgst -sha256 | awk '{print $2}')
        break
    fi
    ls hash* | xargs -n 2 | while read PAIR; do
        PAIRARRAY=(${PAIR})
        if [[ ${#PAIRARRAY[@]} -eq 1 ]]; then
            break
        fi
        cat ${PAIR} | openssl dgst -sha256 -binary > temphash
        rm ${PAIR}
        mv temphash "${PAIRARRAY[0]}"
    done
done

cd /mnt/dbfiles/mahipal/splitfiles/TEMP

echo "Finalizing..."
/bin/aws glacier complete-multipart-upload  --account-id=- --vault-name="final_vault" --upload-id="$uploadId" --checksum="${TREE_HASH}" --archive-size=${ARCHIVE_SIZE} >>commands.txt
RETVAL=$?
if [[ ${RETVAL} -ne 0 ]]; then
    echo "complete-multipart-upload failed with status code: ${RETVAL}" >>commands.txt
    echo "Aborting upload ${uploadId}"  >>commands.txt
    /bin/aws glacier abort-multipart-upload --account-id=- --vault-name="final_vault" --upload-id="${uploadId}" >>commands.txt
    exit 1
fi

echo "--------------"
echo "Deleting temporary commands.txt file"

#rm commands.txt

date2=$(date +"%s")

diff=$(($date2-$date1))

echo "Total Split Duration for Chunk Part Size: $(($diff2/ 3600 )) hours $((($diff2 % 3600) / 60)) minutes $(($diff2 % 60)) seconds" >>commands.txt 

echo "Total Split Duration for hash Part Size: $(($diff3/ 3600 )) hours $((($diff3 % 3600) / 60)) minutes $(($diff3 % 60)) seconds"  >>commands.txt

echo "Total upload Duration: $(($diff/ 3600 )) hours $((($diff % 3600) / 60)) minutes $(($diff % 60)) seconds" >>commands.txt

echo "Done."
exit 0

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多