Téléchargement de fichiers sur un compte S3 à partir de la ligne de commande Linux

75

J'ai plusieurs fichiers volumineux dans mon compte hébergé Linux que je dois télécharger sur mon compte S3. Je ne veux pas les télécharger d'abord, puis les télécharger dans S3.

Est-il possible de le "télécharger" via la ligne de commande Linux? Ou puis-je y accéder via un site Web fonctionnant avec Lynx?

siliciumpi
la source

Réponses:

30

S3cmd fait ce que vous voulez. Télécharger et télécharger des fichiers, synchroniser des répertoires et créer des compartiments.

S3cmd est un outil de ligne de commande gratuit et un client permettant de télécharger, d'extraire et de gérer des données dans Amazon S3 et d'autres fournisseurs de services de stockage en nuage utilisant le protocole S3, tels que Google Cloud Storage ou DreamHost DreamObjects. Il convient particulièrement aux utilisateurs expérimentés qui connaissent bien les programmes en ligne de commande. Il est également idéal pour les scripts batch et la sauvegarde automatisée vers S3, déclenchés à partir de cron, etc.

Alister Bulman
la source
fonctionne comme un charme!
siliconpi
98

Amazon fournit désormais ses propres outils CLI.

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

En utilisant une syntaxe familière, vous pouvez afficher le contenu de vos compartiments S3 dans une liste basée sur des répertoires.

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

Vous pouvez effectuer des téléchargements récursifs et des téléchargements de plusieurs fichiers dans une seule commande au niveau du dossier. AWS CLI exécutera ces transferts en parallèle pour améliorer les performances.

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

Une commande de synchronisation facilite la synchronisation du contenu d'un dossier local avec une copie dans un compartiment S3.

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

La documentation pour les commandes liées aux fichiers est ici .

Drew Noakes
la source
5
réponse la plus complète! :)
SergioFilhow
26

Si vous ne pouvez pas (peut-être que vous êtes sur un hôte partagé) ou si vous ne souhaitez pas installer d'outils supplémentaires, vous pouvez simplement utiliser bash, curl et 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}

Notez que j'ai modifié ce script à partir de celui du lien ci-dessus. J'ai ajouté l' -Loption, car AWS peut insérer une redirection dans cet emplacement. L' -Loption suivra la redirection pour vous.

Une autre mise en garde. Cela ne fonctionnera pas pour les fichiers de plus de 5 Go. Ceux-ci nécessitent un téléchargement en plusieurs parties qui nécessiterait un script plus complexe.

phylae
la source
12

Un script shell compatible POSIX qui requiert OpenSL, Curl et Sed uniquement; prise en charge de AWS Signature version 4, requise pour la région eu-central-1(Francfort) et recommandée pour les autres:

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}"

Remarquez, le script activera côté serveur

Chiffrement AES256 par défaut.

vszakats
la source
Pour les moteurs de recherche: c'est la bonne solution pour eu-central-1 et en général si vous obtenez l'erreurThe authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256
Steen
3

Sinon, vous pouvez essayer https://github.com/minio/mc

mcfournit un minimum d'outils pour travailler avec les systèmes de stockage et de stockage en nuage compatibles avec Amazon S3. Il a des fonctionnalités telles que les téléchargements pouvant être repris, la barre de progression, la copie parallèle. mcest écrit en Golang et publié sous licence Apache v2.

Harshavardhana
la source
C'est une excellente réponse. Je ne veux pas nécessairement le faire en bash, comme le suggèrent les autres (bonnes) réponses. Je ne veux tout simplement pas installer toutes les dépendances requises par awscli.
Michael Barton
1

J'ai trouvé les liaisons AWS de Python dans le botopackage ( pip install boto) très utiles pour le téléchargement de données vers S3.

Le script suivant peut être appelé comme suit: python script_name.py "sub_bucket_name" "*.zip"sub_bucket_nameindique le nom du répertoire dans lequel les fichiers doivent être stockés dans S3, et *.zipconstitue un chemin global désignant un ou plusieurs fichiers à télécharger:

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
la source