2016-12-05 3 views
0

Je veux être en mesure de aws S3 cp avec un seuil de date, mais il ne possède pas de commutateur pour cette fonctionnalité. Donc, je voudrais écrire un script Bash pour cela. Appeler aws s3 ls avec le commutateur --recursive me donne une liste de répertoire avec la date et l'heure que je pense que je peux utiliser pour atteindre mon objectif. Voici un exemple de sortie:Script Bash Pour ajouter un seuil de date à la fonction `cp` de S3

2016-12-01 18:06:40 0 sftp/ 2016-12-01 20:35:39 1024 sftp/.ssh/.id_rsa.swp 2016-12-01 20:35:39 1679 sftp/.ssh/id_rsa 2016-12-01 20:35:39 405 sftp/.ssh/id_rsa.pub

Quel est le moyen le plus efficace pour itérer sur tous les fichiers, mais seulement copier les fichiers plus récents que la date indiquée?

Voici le script (incomplet) J'ai jusqu'à présent:

#!/bin/bash 

while [[ $# -gt 0 ]] 
do 
    key="$1" 

    case $key in 
     -m|--mtime) 
      MTIME="$2" 
      shift 2;; 
     -s|--source) 
      SRCDIR="$2" 
      shift 2;; 
     -d|--dest) 
      DSTDIR="$2" 
      shift 2;; 
     *) 
      #echo "Unknown argument: \"$key\""; exit 1;; 
      break;; 
    esac 
done 

if [ ! -d $DSTDIR ]; then 
    echo "the directory does not exist!"; 
    exit 1; 
fi 

GTDATE="$(date "+%Y%m%d%H%M%S" -d "$MTIME days ago")" 
#echo "Threshold: $GTDATE" 

for f in $(aws s3 ls $SRCDIR --recursive | awk '{ ??? }'); do 
    #aws s3 cp 
done 

Répondre

1

Il est important de savoir si l'horodatage est locale ou UTC.
Si locale est l'Amérique/Los_Angeles, la date peut interpréter correctement les temps (notez la différence 03 vs 11):

$ date -d '20161201T18:06:40' +'%Y%m%dT%H:%M:%S' 
20161201T03:06:40 

$ date -ud '20161201T18:06:40' +'%Y%m%dT%H:%M:%S' 
20161201T11:06:40  

En utilisant -u évite également des problèmes avec l'heure d'été et les changements locaux. En bref la vie est beaucoup plus facile si la date est enregistrée dans un format UTC que la commande date peut relire, et n'a pas d'espaces si awk ou similaire pourrait facilement l'analyser. Par exemple:

$ date -ud '2016-12-01 18:06:40' +'%Y-%m-%dT%H:%M:%S' 
2016-12-01T18:06:40 

Les deux plus facile pour l'ordinateur date et pour les utilisateurs de le lire.
Mais vous avez un horodatage un peu différent.

En supposant que les fichiers n'ont pas de noms avec des retours à la ligne inclus.
Le script après le traitement des options devrait être quelque chose comme ceci:

#!/bin/bash 

SayError(){local a=$1; shift; printf '%s\n' "$0: [email protected]" >&2; exit "$a"; } 

[[ ! -d $dstdir ]] && SayError 1 "The directory $dstdir does not exist!" 
[[ ! -d $srcdir ]] && SayError 2 "The source directory $srcdir doesn't exist" 
[[ -z $mtime ]] && SayError 3 "The value of mtime has not been set." 

gtdate="$(date -ud "$mtime days ago" "+%Y-%m-%dT%H:%M:%S")" 
#echo "Threshold: $gtdate" 

readarray -t files < <(aws s3 ls "$srcdir" --recursive) 
limittime=$(date -ud "$gtdate" +"%s") 

for f in "${files[@]}"; do 
    IFS=' ' read day time size name <<<"$f" 
    filetime=$(date -ud "${day}T${time}" +"%s") 
    if [[ $filetime -gt $limittime ]]; then 
     aws s3 cp "$srcdir/$name" "$destdir/" 
    fi 
done 

Attention: Un Code-testé, s'il vous plaît le lire attentivement.

+0

Y at-il un manque guillemets doubles dans 'filetime = $ (date -ud" $ {jour} T $ {temps}% s) '? – alphadogg

+0

@alphadogg Oui, merci. – sorontar

0

une façon est de trier les s3 ls résultats et la date de coupure ensemble, puis couper le traitement de la liste des s3 lorsque vous appuyez sur la date limite :

cat <(echo "$GTDATE CUTOFF") <(aws s3 ls $SRCDIR --recursive) | 
    sort -dr | 
    awk '{if($3=="CUTOFF"){exit}print}' | 
    xargs -I{} echo aws s3 cp "$SRCDIR/{}" "$DSTDIR/{}" 

(i gauche à echo dans la dernière ligne pour vous de tester et voir ce que les commandes se produiraient enlever le echo à fait aux commandes s3 cp..)

(vous pouvez aussi utiliser s3 sync au lieu de cp pour éviter le re-téléchargement des fichiers qui sont déjà à jour.)

1

Pour la recherche postérité, voici le projet du script final (nous examinons toujours, dans la pratique, vous aurez envie de commenter tous, mais les deux derniers echo appels):

#!/bin/bash 
# 
# S3ToDirSync 
# 
# This script is a custom SFTP-S3 synchronizer utilizing the AWS CLI. 
# 
# Usage: S3ToDirSync.sh -m 7 -d "/home/user" -b "user-data-files" -s "sftp" 
# 
# Notes: 
# The script is hardcoded to exclude syncing of any folder or file on a path containing "~archive" 
# See http://docs.aws.amazon.com/cli/latest/reference/s3/index.html#available-commands for AWS CLI documentation on commands 
# 
# Updated: 12/05/2016 

while [[ $# -gt 0 ]] 
do 
    key="$1" 

    case $key in 
     -m|--mtime) 
      MTIME="$2" # nb of days (from now) to copy 
      shift 2;; 
     -b|--bucket) 
      BUCKET="$2" # the S3 bucket, no trailing slashes 
      shift 2;; 
     -s|--source) # the S3 prefix/path, slashes at start and end of string will be added if not present 
      SRCDIR="$2" 
      shift 2;; 
     -d|--dest) # the root destination folder 
      DSTDIR="$2" 
      shift 2;; 
     *) 
      #echo "Unknown argument: \"$key\""; exit 1;; 
      break;; 
    esac 
done 

# validations 
if [ ! -d $DSTDIR ]; then 
    echo "The destination directory does not exist."; 
    exit 1; 
fi 
if [[ $DSTDIR != *"/" ]]; then 
    DSTDIR=$DSTDIR\/ 
fi 
echo "DSTDIR: $DSTDIR" 

if [ -z $BUCKET ]; then 
    echo "The bucket value has not been set."; 
    exit 1; 
fi 

if [[ $BUCKET == *"/"* ]]; then 
    echo "No slashes (/) in bucket arg."; 
    exit 1; 
fi 
# add trailing slash 
BUCKET=$BUCKET\/ 
echo "BUCKET: $BUCKET" 

if [ -z $MTIME ]; then 
    echo "The mtime value has not been set."; 
    exit 1; 
fi 

# $SRCDIR may be empty, to copy everything in a bucket, but add a trailing slash if missing 
if [ ! -z $SRCDIR ] && [[ $SRCDIR != *"/" ]]; then 
    SRCDIR=$SRCDIR\/ 
fi 
echo "SRCDIR: $SRCDIR" 

SRCPATH=s3://$BUCKET$SRCDIR 
echo "SRCPATH: $SRCPATH" 

LIMITTIME=$(date -ud "$MTIME days ago" "+%s") 
#echo "Threshold UTC Epoch: $LIMITTIME" 

readarray -t files < <(aws s3 ls "$SRCPATH" --recursive) # TODO: ls will return up to a limit of 1000 rows, which could timeout or not be enough 
for f in "${files[@]}"; do 
    IFS=' ' read day time size name <<<"$f" 
    FILETIME=$(date -ud "${day}T${time}" "+%s") 
    # if S3 file more recent than threshold AND if not in an "~archive" folder 
    if [[ $FILETIME -gt $LIMITTIME ]] && [[ $name != *"~archive"* ]]; then 
     name="${name/$SRCDIR/}" # truncate ls returned name by $SRCDIR, since S3 returns full path 
     echo "$SRCPATH $name" 
     destpath=$DSTDIR$name 
     echo "to $destpath" 
     # if a directory (trailing slash), mkdir in destination if necessary 
     if [[ $name == *"/" ]] && [ ! -d $destpath ]; then 
      echo "mkdir -p $destpath" 
      mkdir -p $destpath 
     # else a file, use aws s3 sync to benefit from rsync-like checks 
     else 
      echo "aws s3 sync $SRCPATH$name $destpath" 
      aws s3 sync $SRCPATH$name $destpath 
      # NOTE: if a file was on S3 then deleted inside MTIME window, do we delete on SFTP server? If so, add --delete 
     fi 
    fi 
done