#!/usr/bin/env bash HOST_NAME=$(hostname) DAY=$(date +%u) HERE=$(dirname "$0") PASSPHRASE=1234567890 EXT=tgz.gpg # Log-Datei schreiben. # # Die Ausgabe geht auch auf STDOUT, dadurch kann die vollständige Ausgabe, # einschließlich Status- und Fehlermeldungen der Programme in ein erweitertes # Log für die Fehlersuche umgeleitet werden. # # $1 - Typ, z.B. INFO, WARN, ERROR, etc. # $2 ff. - die Meldung, die ins Log geschreiben wird # log() { local type=$1 if [ "$type" == "ERROR" ]; then ERROR=0; fi shift 1 echo "$(date '+%d.%m.%Y %H:%M:%S') - $type $@" | sudo tee -a $LOG_FILE } # Ist $1 in der Liste der restlichen args $2, $3 ... # # zB. if is_in "foo" "foo" "bar" "foo bar" ; then ... # Leere Liste liefert immer false # is_in() { local search="$1" shift 1 local e for e in "$@"; do [[ "$e" == "$search" ]] && return 0; done return 1 } # Alle Verzechnisnamen in einem Verzeichnis holen. # # $1 - Verzeichnis in dem gesucht wird als absoluter Pfad # $2 ff. - auszuschliessende Verzeichnisse (kann leer bleiben) # iterate_dirs_in() { local dirname local root=$1 shift 1 for dir in $(sudo find "$root" -maxdepth 1 -type d \! -wholename "$root"); do dirname=$(basename $dir) if ! is_in "$dirname" "$@"; then echo "$dirname" fi done } # create directory if it not exists # # $1 - dir to check # check_directory() { local dir=$1 if [ -d "$1" ]; then return 0 else mkdir -p "$1" && return 0 sudo mkdir -p "$1" && return 0 log ERROR "### could not create directory $1!" # no chance to recover exit 1 fi } # Verzeichnis löschen # # Im Fehlerfall wird rc=1 zurückgegeben # # $1 - zu löschendes Verzeichnis # delete_dir() { local dir=$1 sudo rm -rf "$dir" && return 0 log ERROR "### could not delete directory $1!" # return error, so caller can decide what to do return 1 } # Slashes "/" im Pfadnamen durch Dashes "-" ersetzen, so dass der String als Dateiname verwendet werden kann. # # $1 - path backup_file_prefix() { echo "$1" | sed -E 's/^\///' | sed -E 's/\//-/g' } # Verzeichnise in .tgz.gpg-Dateien sichern. # # $1 - Verzeichnis, das gesichert wird: alle Verzeichnisse darunter werden einzeln als .tgz.gpg-Datei gesichert # $2 - Zielverzeichnis für .tgz.gpg-Dateien # $3 ff. - Verzeichnisse, die nicht gesichert werden sollen (kann leer bleiben) # backup_all_dirs() { local root=$1 local target=$2 local prefix=$(backup_file_prefix $root) local tar_file local dir shift 2 for dir in $(iterate_dirs_in "$root" "$@"); do tar_file="$target/$prefix-$dir.$EXT" backup_dir "$root" "$tar_file" "$dir" create_list "$tar_file" "$dir" test_integrity "$tar_file" done } # Einzelnes Verzeichnis sichern. # # $1 - Pfad um Verzeichnis, das gesichert werden soll # $2 - Zielpfad und -name für das Archiv # $2 - zu sicherndes Verzeichnis # backup_dir() { local root=$1 local archive=$2 local dir=$3 log INFO "--- Backup $root/$dir -> $archive" sudo tar -c -z --numeric-owner --one-file-system --exclude "@eaDir" -C "$root" "$dir" | sudo gpg --batch -c --passphrase $PASSPHRASE -o "$archive" local rc=$? if [ "$rc" == "0" ] ; then log INFO "*** success" else log ERROR "### see full log" fi } # Inhalt des Archivs in eine Textdatei ausgeben. # # $1 - Archiv # create_list() { local archive=$1 log INFO "--- List $archive" sudo gpg --batch --decrypt --passphrase $PASSPHRASE "$archive" | sudo tar -tzv | sudo tee $archive.txt >/dev/null local rc=$? if [ "$rc" == "0" ] ; then log INFO "*** success" else log ERROR "### see full log" fi } # Integrität des Archivs testen, indem es entschlüsselt, entpackt # und der Inhalt auf /dev/null ausgegeben wird. # # $1 - Archiv # test_integrity() { local archive=$1 log INFO "--- Check integrity of $archive" sudo gpg --batch --decrypt --passphrase $PASSPHRASE "$archive" | sudo tar -xzO >/dev/null local rc=$? if [ "$rc" == "0" ] ; then log INFO "*** success" else log ERROR "### see full log" fi } # Restore aus Archiv # # Wird nach pwd ausgegeben! # # $1 - Archiv, ggf. mit Pfad # $2 ff. - zurückzusichernde Dateien/Verzeichnisse # restore() { local archive=$1 shift 1 sudo gpg --batch --decrypt --passphrase $PASSPHRASE "$archive" | sudo tar -xzv $@ >/dev/null local rc=$? if [ "$rc" == "0" ] ; then log INFO "*** success" else log ERROR "### see full log" fi } # Liste der Archives auf stdout ausgeben # # Zeigt alle Archive incl. des letzten Verzeichnisses an # # z.B. # backup.7/volume1-data-Web.tgz.gpg # media/volume1-media-books.tgz.gpg # # $1 - root path i.d.R. ein Verzeichnis oberhalb, damit alle täglichen Backups angezeigt werden # list_archives() { local target=$1 local targ=${target//\//\\\/} # slashes escapen echo "#$targ#" sudo find "$target" -type f -name "*.gpg" | sed -E "s/^$targ//" } # *** NAS Test *** nas_test() { LOG_FILE="/volume1/nfs/Server/tmp/backup.log" log INFO "*** *** Begin NAS backup (data, nfs, media/books, media/music)" TARGET_DIR="/volume1/nfs/backups/tmp/backup.$DAY" EXCLUDE_DIRS=("@eaDir" "Temporary Items" "lost+found") delete_dir $TARGET_DIR # bei Fehler werden die Dateien hoffentlich überschrieben check_directory $TARGET_DIR # data backup_all_dirs "/volume1/data" "$TARGET_DIR" "${EXCLUDE_DIRS[@]}" EXCLUDE_DIRS=("@eaDir" "Temporary Items" "lost+found" backups) # nfs backup_all_dirs "/volume1/nfs" "$TARGET_DIR" "${EXCLUDE_DIRS[@]}" BACKUP_ROOT=/volume1/nfs/backups/tmp TARGET_DIR="$BACKUP_ROOT/media" EXCLUDE_DIRS=("@eaDir" "Temporary Items" "lost+found" serien tmp video "video.archive") check_directory $TARGET_DIR # media/books media/music backup_all_dirs "/volume1/media" "$TARGET_DIR" "${EXCLUDE_DIRS[@]}" log INFO "*** End of NAS backup" list_archives $BACKUP_ROOT } # *** NATHAN Test *** nathan_test() { LOG_FILE=/var/docker/tmp/backup.log log INFO "*** *** Begin nathan server backup" BACKUP_ROOT=/var/docker/tmp TARGET_DIR="$BACKUP_ROOT/backup.$DAY" delete_dir $TARGET_DIR check_directory $TARGET_DIR backup_all_dirs "/var" "$TARGET_DIR" docker backup_all_dirs "/var/docker" "$TARGET_DIR" vol tmp backup_all_dirs "/var/docker/vol" "$TARGET_DIR" log INFO "*** End of nathan server backup" list_archives $BACKUP_ROOT } # *** HANILLER Test *** hamiller_test() { LOG_FILE=/var/docker/tmp/backup.log log INFO "*** *** Begin hamiller server backup" BACKUP_ROOT=/var/docker/tmp TARGET_DIR="$BACKUP_ROOT/backup.$DAY" delete_dir $TARGET_DIR check_directory $TARGET_DIR backup_all_dirs "/var" "$TARGET_DIR" # docker # backup_all_dirs "/var/docker" "$TARGET_DIR" vol tmp # backup_all_dirs "/var/docker/vol" "$TARGET_DIR" log INFO "*** End of hamiller server backup" list_archives $BACKUP_ROOT } test() { for i in "$@"; do echo "$i"; done } isFunction() { declare -Ff "$1" ; } #nas_test #nathan_test #hamiller_test #test1 list1() { EXCL=("eaDir" "Temporary Items" "lost+found" backups) ONE="erster #1" TWO="zweiter #1" #for i in "${a[@]}"; do echo "$i"; done } list2() { EXCL=("@eaDir" "Temporary Items" "lost+found") ONE="eins2" TWO="zwei2" #for i in "${a[@]}"; do echo "$i"; done } count=1 isFunction list4 while [ $(isFunction list$count) ]; do list$count for i in "${EXCL[@]}"; do echo "$i"; done echo "$count: one = ${ONE} / two = ${TWO}" let "count += 1" done exit TARGET_DIR=/var/docker/tmp/two echo "#" echo "### gpg ###################################################" echo "#" date +%H:%M:%S.%N echo "--- tar -c ------------------------------------------------" cd $RUN_DIR sudo tar -c -z --numeric-owner --one-file-system "$BACKUP_DIR/$SOURCE" | sudo gpg --batch -c --passphrase $PASSPHRASE -o "$TARGET_DIR/$SOURCE.tgz.gpg" date +%H:%M:%S.%N echo "--- tar -t ------------------------------------------------" cd $TARGET_DIR sudo gpg --batch --decrypt --passphrase $PASSPHRASE "$TARGET_DIR/$SOURCE.tgz.gpg" 2>/dev/null | sudo tar -tz | sudo tee tar_list.txt >/dev/null date +%H:%M:%S.%N echo "--- tar -x ------------------------------------------------" sudo gpg --batch --decrypt --passphrase $PASSPHRASE "$TARGET_DIR/$SOURCE.tgz.gpg" 2>/dev/null | sudo tar -xzv $RESTORE >/dev/null date +%H:%M:%S.%N