#!/bin/bash [[ "$TRACE" ]] && set -x DEBUG=${DEBUG:-"Unknown Error"} function log { now=`date +"%Y-%m-%d %T"` echo "[${now}] $1" } function usage { cat <<-EOF Usage: $PROGNAME [OPTIONS] Sync s3 directory locally and backup changed files on exit --force-restore restore even if local directory is not empty eg: $PROGNAME /data s3://bucket/dir EOF } function error_exit { log "${1:-"Unknown Error"}" 1>&2 exit 1 } PARSED_OPTIONS=$(getopt -n "$0" -o f --long "force-restore" -- "$@") if [ $? -ne 0 ]; then exit 1 fi eval set -- "$PARSED_OPTIONS" while true; do case "$1" in -f|--force-restore) FORCE_RESTORE="true" shift;; --) shift break;; esac done PROGNAME=$0 S3_PROG=/s5cmd LOCAL=$1 REMOTE=$2 WATCH_EVENTS=modify function restore { if [ "$(ls -A $LOCAL)" ]; then if [[ ${FORCE_RESTORE:false} == 'true' ]]; then error_exit "local directory is not empty" fi fi log "restoring $REMOTE => $LOCAL" if ! $S3_PROG sync "$REMOTE/*" "$LOCAL"; then error_exit "restore failed" fi } function backup { log "backup $LOCAL => $REMOTE" if ! $S3_PROG sync "$LOCAL" "$REMOTE" $S3_SYNC_FLAGS; then log "backup failed" 1>&2 return 1 fi } function final_backup { log "backup $LOCAL => $REMOTE" while ! $S3_PROG sync "$LOCAL" "$REMOTE" $S3_SYNC_FLAGS; do log "backup failed, will retry" 1>&2 sleep 1 done exit 0 } function idle { log "ready" log "RESTORE_INTERVAL: ${RESTORE_INTERVAL}" while true; do restore if [[ -v RESTORE_INTERVAL ]]; then backup timeout ${RESTORE_INTERVAL} inotifywait -m -e modify -e move -e create -e delete --timefmt '%Y-%m-%d %H:%M:%S' --format '%T %f' $LOCAL | while read date time file; do log "The file '$file' appeared in directory '$path' via '$action'"; backup; done else log "Without restore interval" inotifywait -m -e modify -e move -e create -e delete --timefmt '%Y-%m-%d %H:%M:%S' --format '%T %f' $LOCAL | while read date time file do log "The file '$file' appeared in directory '$path' via '$action'" backup done fi done } trap final_backup SIGHUP SIGINT SIGTERM trap "backup; idle" USR1 idle