Hochladen von Dateien auf das S3-Konto über die Linux-Befehlszeile

74

In meinem von Linux gehosteten Konto befinden sich mehrere große Dateien, die ich auf mein S3-Konto hochladen muss. Ich möchte sie nicht zuerst herunterladen und dann in S3 hochladen.

Kann ich es auf irgendeine Weise über die Linux-Befehlszeile "hochladen"? Oder kann ich über eine Website mit Lynx darauf zugreifen?

siliconpi
quelle

Antworten:

30

S3cmd macht was Sie wollen. Hochladen und Herunterladen von Dateien, Synchronisieren von Verzeichnissen und Erstellen von Buckets.

S3cmd ist ein kostenloses Befehlszeilentool und ein Client zum Hochladen, Abrufen und Verwalten von Daten in Amazon S3 und anderen Cloud-Speicherdienstanbietern, die das S3-Protokoll verwenden, z. B. Google Cloud Storage oder DreamHost DreamObjects. Es ist am besten für Hauptbenutzer geeignet, die mit Befehlszeilenprogrammen vertraut sind. Es ist auch ideal für Batch-Skripte und automatisierte Sicherungen auf S3, die von cron usw. ausgelöst werden.

Alister Bulman
quelle
klappt wunderbar!
Siliconpi
97

Amazon bietet jetzt auch eigene CLI-Tools an.

Von http://aws.amazon.com/cli/

Mit der bekannten Syntax können Sie den Inhalt Ihrer S3-Buckets in einer verzeichnisbasierten Liste anzeigen.

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

Sie können mehrere Dateien in einem einzigen Befehl auf Ordnerebene rekursiv hochladen und herunterladen. Die AWS CLI führt diese Übertragungen zur Leistungssteigerung parallel aus.

$ 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
...

Ein Synchronisierungsbefehl erleichtert das Synchronisieren des Inhalts eines lokalen Ordners mit einer Kopie in einem S3-Bucket.

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

Dokumentation für dateibezogene Befehle finden Sie hier .

Drew Noakes
quelle
5
vollständigste Antwort! :)
SergioFilhow
26

Wenn Sie dies nicht können (vielleicht befinden Sie sich auf einem gemeinsam genutzten Host) oder keine zusätzlichen Tools installieren möchten, können Sie einfach bash, curl und openssl verwenden.

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}

Beachten Sie, dass ich dieses Skript gegenüber dem obigen Link geändert habe. Ich habe die -LOption hinzugefügt, da AWS dort möglicherweise eine Umleitung einfügt. Die -LOption folgt der Weiterleitung für Sie.

Noch eine Einschränkung. Dies funktioniert nicht für Dateien, die größer als 5 GB sind. Diese erfordern einen mehrteiligen Upload, der ein komplexeres Skript erfordert.

Phylae
quelle
12

Ein POSIX-kompatibles Shell-Skript, für das nur openssl, curl und sed erforderlich sind. Unterstützung von AWS Signature Version 4, die für die Region eu-central-1(Frankfurt) erforderlich und für die anderen empfohlen ist:

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/[email protected]/bin/openssl ]; then
    /usr/local/opt/[email protected]/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}"

Beachten Sie, dass das Skript serverseitig aktiviert wird

AES256-Verschlüsselung standardmäßig.

vszakats
quelle
Für die Suchmaschinen: Dies ist die richtige Lösung für eu-central-1 und im Allgemeinen, wenn Sie den Fehler erhaltenThe authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256
Steen
3

Alternativ können Sie https://github.com/minio/mc versuchen

mcBietet minimale Tools für die Arbeit mit Amazon S3-kompatiblen Cloud-Speichern und Dateisystemen. Es verfügt über Funktionen wie wiederkehrende Uploads, Fortschrittsbalken, paralleles Kopieren. mcist in Golang geschrieben und unter der Apache-Lizenz v2 veröffentlicht.

Harshavardhana
quelle
Das ist eine großartige Antwort. Ich möchte es nicht unbedingt in bash machen, wie die anderen (guten) Antworten andeuten. Ich möchte einfach nicht alle Abhängigkeiten installieren, die awscli benötigt.
Michael Barton
1

Ich habe festgestellt, dass die AWS-Bindungen von Python im botopackage ( pip install boto) hilfreich sind, um Daten in S3 hochzuladen.

Das folgende Skript kann folgendermaßen aufgerufen werden: python script_name.py "sub_bucket_name" "*.zip"Dabei sub_bucket_namegibt es den Namen des Verzeichnisses an, in dem die Dateien in S3 gespeichert werden sollen, und *.zipeinen globalen Pfad, der eine oder mehrere hochzuladende Dateien angibt :

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
duhaime
quelle