การอัพโหลดไฟล์ไปยังบัญชี S3 จากบรรทัดคำสั่ง Linux


74

ฉันมีไฟล์ขนาดใหญ่หลายไฟล์นั่งอยู่ในบัญชีที่โฮสต์บน Linux ซึ่งฉันต้องอัปโหลดไปยังบัญชี S3 ของฉัน ฉันไม่ต้องการดาวน์โหลดก่อนแล้วจึงอัปโหลดเป็น S3

มีวิธีใดบ้างที่ฉันสามารถ "อัปโหลด" ผ่านทางบรรทัดคำสั่ง Linux หรือฉันสามารถเข้าถึงผ่านเว็บไซต์ที่ทำงานกับ Lynx ได้หรือไม่?

คำตอบ:


30

S3cmdทำในสิ่งที่คุณต้องการ การอัพโหลดและดาวน์โหลดไฟล์ซิงค์ไดเรกทอรีและสร้างที่เก็บข้อมูล

S3cmd เป็นเครื่องมือบรรทัดคำสั่งฟรีและไคลเอนต์สำหรับการอัพโหลดดึงและจัดการข้อมูลใน Amazon S3 และผู้ให้บริการจัดเก็บข้อมูลบนคลาวด์อื่น ๆ ที่ใช้โปรโตคอล S3 เช่น Google Cloud Storage หรือ DreamHost DreamObjects เหมาะที่สุดสำหรับผู้ใช้ระดับสูงที่คุ้นเคยกับโปรแกรมบรรทัดคำสั่ง นอกจากนี้ยังเหมาะสำหรับชุดสคริปต์และการสำรองข้อมูลอัตโนมัติถึง S3, เรียกจาก cron ฯลฯ


ทำงานเหมือนจับใจ!
siliconpi

97

ตอนนี้ Amazon ก็จัดหาเครื่องมือ CLI ของตัวเองเช่นกัน

จากhttp://aws.amazon.com/cli/

ใช้ไวยากรณ์ที่คุ้นเคยคุณสามารถดูเนื้อหาของ S3 S3 ของคุณในรายชื่อไดเรกทอรี

$ aws s3 ls s3://mybucket
      LastWriteTime     Length Name
      -------------     ------ ----
                           PRE myfolder/
2013-09-03 10:00:00       1234 myfile.txt
...

คุณสามารถทำการอัพโหลดซ้ำและดาวน์โหลดไฟล์หลายไฟล์ในคำสั่งระดับโฟลเดอร์เดียว AWS CLI จะเรียกใช้การถ่ายโอนแบบขนานเพื่อประสิทธิภาพที่เพิ่มขึ้น

$ aws s3 cp myfolder s3://mybucket/myfolder --recursive
upload: myfolder/file1.txt to s3://mybucket/myfolder/file1.txt
upload: myfolder/subfolder/file1.txt to s3://mybucket/myfolder/subfolder/file1.txt
...

คำสั่ง sync ทำให้ง่ายต่อการซิงโครไนซ์เนื้อหาของโฟลเดอร์ในเครื่องด้วยสำเนาในที่เก็บ S3

$ aws s3 sync myfolder s3://mybucket/myfolder --exclude *.tmp
upload: myfolder/newfile.txt to s3://mybucket/myfolder/newfile.txt
...

เอกสารคำสั่งที่เกี่ยวข้องกับไฟล์ที่นี่


5
คำตอบที่สมบูรณ์ที่สุด! :)
SergioFilhow

26

หากคุณไม่สามารถ (บางทีคุณอยู่ในโฮสต์ที่แชร์) หรือไม่ต้องการติดตั้งเครื่องมือพิเศษเป็นไปได้ที่จะใช้ bash, curl และ openssl

http://tmont.com/blargh/2014/1/uploading-to-s3-in-bash

file=/path/to/file/to/upload.tar.gz
bucket=your-bucket
resource="/${bucket}/${file}"
contentType="application/x-compressed-tar"
dateValue=`date -R`
stringToSign="PUT\n\n${contentType}\n${dateValue}\n${resource}"
s3Key=xxxxxxxxxxxxxxxxxxxx
s3Secret=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
signature=`echo -en ${stringToSign} | openssl sha1 -hmac ${s3Secret} -binary | base64`
curl -L -X PUT -T "${file}" \
  -H "Host: ${bucket}.s3.amazonaws.com" \
  -H "Date: ${dateValue}" \
  -H "Content-Type: ${contentType}" \
  -H "Authorization: AWS ${s3Key}:${signature}" \
  https://${bucket}.s3.amazonaws.com/${file}

โปรดทราบว่าฉันแก้ไขสคริปต์นี้จากลิงค์ด้านบน ฉันเพิ่ม-Lตัวเลือกเนื่องจาก AWS อาจแทรกการเปลี่ยนเส้นทางในนั้น -Lตัวเลือกที่จะเป็นไปตามการเปลี่ยนเส้นทางสำหรับคุณ

หนึ่งข้อแม้อื่น ๆ สิ่งนี้จะไม่ทำงานกับไฟล์ที่มีขนาดใหญ่กว่า 5GB สิ่งเหล่านั้นต้องการการอัปโหลดหลายส่วนซึ่งจะต้องมีสคริปต์ที่ซับซ้อนมากขึ้น


12

เชลล์สคริปต์ที่สอดคล้องกับ POSIX ที่ต้องการ openssl, curl และ sed เท่านั้น รองรับ AWS Signature Version 4 ซึ่งจำเป็นสำหรับภูมิภาค eu-central-1(แฟรงค์เฟิร์ต) และแนะนำสำหรับอื่น ๆ :

https://gist.github.com/vszakats/2917d28a951844ab80b1

#!/bin/sh -u

# To the extent possible under law, Viktor Szakats (vszakats.net)
# has waived all copyright and related or neighboring rights to this
# script.
# CC0 - https://creativecommons.org/publicdomain/zero/1.0/

# Upload a file to Amazon AWS S3 using Signature Version 4
#
# docs:
#    https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
#
# requires:
#    curl, openssl 1.x, GNU sed, LF EOLs in this file

fileLocal="${1:-example-local-file.ext}"
bucket="${2:-example-bucket}"
region="${3:-}"
storageClass="${4:-STANDARD}"  # or 'REDUCED_REDUNDANCY'

m_openssl() {
  if [ -f /usr/local/opt/openssl@1.1/bin/openssl ]; then
    /usr/local/opt/openssl@1.1/bin/openssl "$@"
  elif [ -f /usr/local/opt/openssl/bin/openssl ]; then
    /usr/local/opt/openssl/bin/openssl "$@"
  else
    openssl "$@"
  fi
}

m_sed() {
  if which gsed > /dev/null 2>&1; then
    gsed "$@"
  else
    sed "$@"
  fi
}

awsStringSign4() {
  kSecret="AWS4$1"
  kDate=$(printf         '%s' "$2" | m_openssl dgst -sha256 -hex -mac HMAC -macopt "key:${kSecret}"     2>/dev/null | m_sed 's/^.* //')
  kRegion=$(printf       '%s' "$3" | m_openssl dgst -sha256 -hex -mac HMAC -macopt "hexkey:${kDate}"    2>/dev/null | m_sed 's/^.* //')
  kService=$(printf      '%s' "$4" | m_openssl dgst -sha256 -hex -mac HMAC -macopt "hexkey:${kRegion}"  2>/dev/null | m_sed 's/^.* //')
  kSigning=$(printf 'aws4_request' | m_openssl dgst -sha256 -hex -mac HMAC -macopt "hexkey:${kService}" 2>/dev/null | m_sed 's/^.* //')
  signedString=$(printf  '%s' "$5" | m_openssl dgst -sha256 -hex -mac HMAC -macopt "hexkey:${kSigning}" 2>/dev/null | m_sed 's/^.* //')
  printf '%s' "${signedString}"
}

iniGet() {
  # based on: https://stackoverflow.com/questions/22550265/read-certain-key-from-certain-section-of-ini-file-sed-awk#comment34321563_22550640
  printf '%s' "$(m_sed -n -E "/\[$2\]/,/\[.*\]/{/$3/s/(.*)=[ \\t]*(.*)/\2/p}" "$1")"
}

# Initialize access keys

if [ -z "${AWS_CONFIG_FILE:-}" ]; then
  if [ -z "${AWS_ACCESS_KEY:-}" ]; then
    echo 'AWS_CONFIG_FILE or AWS_ACCESS_KEY/AWS_SECRET_KEY envvars not set.'
    exit 1
  else
    awsAccess="${AWS_ACCESS_KEY}"
    awsSecret="${AWS_SECRET_KEY}"
    awsRegion='us-east-1'
  fi
else
  awsProfile='default'

  # Read standard aws-cli configuration file
  # pointed to by the envvar AWS_CONFIG_FILE
  awsAccess="$(iniGet "${AWS_CONFIG_FILE}" "${awsProfile}" 'aws_access_key_id')"
  awsSecret="$(iniGet "${AWS_CONFIG_FILE}" "${awsProfile}" 'aws_secret_access_key')"
  awsRegion="$(iniGet "${AWS_CONFIG_FILE}" "${awsProfile}" 'region')"
fi

# Initialize defaults

fileRemote="${fileLocal}"

if [ -z "${region}" ]; then
  region="${awsRegion}"
fi

echo "Uploading" "${fileLocal}" "->" "${bucket}" "${region}" "${storageClass}"
echo "| $(uname) | $(m_openssl version) | $(m_sed --version | head -1) |"

# Initialize helper variables

httpReq='PUT'
authType='AWS4-HMAC-SHA256'
service='s3'
baseUrl=".${service}.amazonaws.com"
dateValueS=$(date -u +'%Y%m%d')
dateValueL=$(date -u +'%Y%m%dT%H%M%SZ')
if hash file 2>/dev/null; then
  contentType="$(file -b --mime-type "${fileLocal}")"
else
  contentType='application/octet-stream'
fi

# 0. Hash the file to be uploaded

if [ -f "${fileLocal}" ]; then
  payloadHash=$(m_openssl dgst -sha256 -hex < "${fileLocal}" 2>/dev/null | m_sed 's/^.* //')
else
  echo "File not found: '${fileLocal}'"
  exit 1
fi

# 1. Create canonical request

# NOTE: order significant in ${headerList} and ${canonicalRequest}

headerList='content-type;host;x-amz-content-sha256;x-amz-date;x-amz-server-side-encryption;x-amz-storage-class'

canonicalRequest="\
${httpReq}
/${fileRemote}

content-type:${contentType}
host:${bucket}${baseUrl}
x-amz-content-sha256:${payloadHash}
x-amz-date:${dateValueL}
x-amz-server-side-encryption:AES256
x-amz-storage-class:${storageClass}

${headerList}
${payloadHash}"

# Hash it

canonicalRequestHash=$(printf '%s' "${canonicalRequest}" | m_openssl dgst -sha256 -hex 2>/dev/null | m_sed 's/^.* //')

# 2. Create string to sign

stringToSign="\
${authType}
${dateValueL}
${dateValueS}/${region}/${service}/aws4_request
${canonicalRequestHash}"

# 3. Sign the string

signature=$(awsStringSign4 "${awsSecret}" "${dateValueS}" "${region}" "${service}" "${stringToSign}")

# Upload

curl -s -L --proto-redir =https -X "${httpReq}" -T "${fileLocal}" \
  -H "Content-Type: ${contentType}" \
  -H "Host: ${bucket}${baseUrl}" \
  -H "X-Amz-Content-SHA256: ${payloadHash}" \
  -H "X-Amz-Date: ${dateValueL}" \
  -H "X-Amz-Server-Side-Encryption: AES256" \
  -H "X-Amz-Storage-Class: ${storageClass}" \
  -H "Authorization: ${authType} Credential=${awsAccess}/${dateValueS}/${region}/${service}/aws4_request, SignedHeaders=${headerList}, Signature=${signature}" \
  "https://${bucket}${baseUrl}/${fileRemote}"

โปรดสังเกตว่าสคริปต์จะเปิดใช้งานฝั่งเซิร์ฟเวอร์

การเข้ารหัส AES256 โดยค่าเริ่มต้น


สำหรับเครื่องมือค้นหา: นี่คือทางออกที่ถูกต้องสำหรับ eu-central-1 และโดยทั่วไปถ้าคุณได้รับข้อผิดพลาดThe authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256
Steen

3

หรือคุณสามารถลองhttps://github.com/minio/mc

mcมีเครื่องมือน้อยที่สุดในการทำงานกับที่เก็บข้อมูลบนคลาวด์ที่เข้ากันได้กับ Amazon S3 และระบบไฟล์ มันมีคุณสมบัติเช่นการอัพโหลดต่อ, แถบความคืบหน้า, สำเนาแบบขนาน mcเขียนใน Golang และเผยแพร่ภายใต้ Apache License v2


นี่คือคำตอบที่ดี ฉันไม่ต้องการที่จะทำมันด้วยการทุบตีเพราะคำตอบอื่น ๆ (ดี) กำลังแนะนำ ฉันไม่ต้องการที่จะติดตั้งการอ้างอิงทั้งหมดที่ awscli ต้องการ
Michael Barton

1

ฉันพบ AWS ของ Python ในbotoแพคเกจ ( pip install boto) จะเป็นประโยชน์สำหรับการอัปโหลดข้อมูลไปยัง S3

สคริปต์ต่อไปนี้สามารถเรียกว่า like: python script_name.py "sub_bucket_name" "*.zip"โดยที่sub_bucket_nameระบุชื่อของไดเรกทอรีที่ควรจัดเก็บไฟล์ใน S3 และ*.zipเป็นเส้นทางแบบกลมที่กำหนดให้อัปโหลดไฟล์อย่างน้อยหนึ่งไฟล์:

import sys, glob, os, boto
from boto.s3.key import Key

def percent_cb(complete, total):
    sys.stdout.write('.')
    sys.stdout.flush()

id = '< your id here >'               # AWS Access Key ID
secret = '< your secret here >'       # AWS Secret Access Key
bucket_name = '< your bucket here >'  # Bucket wherein content will be stored
conn = boto.connect_s3(id, secret)    # Establish a connection to S3
bucket = conn.get_bucket(bucket_name, validate=False)  # Connect to bucket
k  = Key(bucket)                      # Connect to the bucket's key

for i in glob.glob(sys.argv[2]):      # Read in files to push to S3

        sub_bucket = sys.argv[1]  # Directory within bucket where files will be stored
        k.key = sub_bucket + "/" + os.path.basename(i) # Path each uploaded file will have on S3

        k.set_contents_from_filename(i, cb=percent_cb, num_cb=10)  # Push data to S3

        print 'Uploading %s to Amazon S3 bucket %s' % (i, bucket_name)  # Report status
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.