diff --git a/.gitignore b/.gitignore index 8c2b884..9624330 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ # Built Visual Studio Code Extensions *.vsix +._server-backup.code-workspace diff --git a/README.md b/README.md index 86c4bf4..02f87fb 100644 --- a/README.md +++ b/README.md @@ -9,5 +9,22 @@ Scripte für Um möglichst wenige Abhängigkeiten zu erzeugen, werden primär Bordmittel verwendet (tar, gpg, find, rsync, etc.). Das sollte auch die Pflege vereinfachen. -Gesichert wird vom Server das Verzeichnis ```/var```, wobei ```/var/docker``` und ```/var/docker/vol``` gesondert behandelt werden. Von der NAS werden die Daten-Shares, sowie die Bücher- und Musik-Verzeichnisse gesichert. Die Serien- und Video-Verzeichnisse werden hin und wieder auf externe Datenträger kopiert. +Täglich gesichert wird von den Servern das Verzeichnis ```/var``` (für nathan werden ```/var/docker``` und ```/var/docker/vol``` gesondert behandelt). Von der NAS werden die Daten-Shares (z.Zt. ```data``` uns ```nfs```) täglich gesichert, sowie die Bücher- und Musik-Verzeichnisse wöchentlich. Die Serien- und Video-Verzeichnisse werden im Zug des Exports auf externe Datenträger kopiert. +Das gibt auf der NAS unter ```/volume1/nfs/backups``` die folgende Struktur (1 = MO): + +``` +daily/nathan/backup.1 20GB/ 0:40h + ... + backup.7 + hamiller/backup.1 35GB/ 0:35h + ... + backup.7 + synology/backup.1/data \ + nfs / 60GB/ 1:40h + ... + backup.7/data + backup.7/nfs +weekly/synology 320GB/ 9:30h +logs// +``` diff --git a/TODO.md b/TODO.md index 2038a11..91581d0 100644 --- a/TODO.md +++ b/TODO.md @@ -1,46 +1,9 @@ -### tar -``` -#!/bin/bash -date -cd /var/docker -for f in *; do - sudo tar -c -z -v --numeric-owner --one-file-system -f /var/docker/tmp/$(basename $f).tar.gz $f -done -date -``` - -### gpg - -``` -passphrase=$(head -n 1 /var/secret.key) -gpg --symmetric --batch --yes --passphrase $passphrase --output some.gpg toEncrypt.txt - -# oder - -gpg --batch -c --passphrase-file /var/secret.key -o some.gpg toencrypt.txt - -# oder - -gpg --batch --symmetric --passphrase 1234567890 test.txt # -> test.txt.gpg - -gpg --batch --decrypt --passphrase 1234567890 -o test.txt test.txt.gpg # ohne -o to stdout - -``` - -### ssh - -auf nathan - -je Server ssh -mount-point-/Server/bin/backup/cron.sh -mount-point-/Server/log/backup/-server-/backup.x.log - -### TODO +### TODOs nextcloud: -- vol/nextcloud/data/data/hb zeigt auf NAS-share --> alles auf NAS, bzw. alles auf Server? --> oder symlink in NFS-Share? --> falls auf NAS, per NFS? +- (x) vol/nextcloud/data/data/hb zeigt auf NAS-share +-> alles auf Server backup MAC - ccc 2x 2TB intern (weekly) @@ -49,20 +12,28 @@ backup MAC - TODO: Kalendereintrag für wöchentlichen backup nas-backup daily -- tar, gpg to nas -- server: /var dir to file (evtl. /var/docker + /var/docker/vol extra - tar-Syntax?) -- nas: //data, //nfs, //nextcloud(?) dir to file -- auf nas unter //backup sammeln - - TODO: tar syntax (find | py) - - TODO: gpg syntax - - TODO: file handling - - TODO: script (python?) +- (x) tar, gpg to nas +- (x) server: /var dir to file (evtl. /var/docker + /var/docker/vol extra - tar-Syntax?) +- (x) nas: //data, //nfs, //nextcloud(?) dir to file +- (x) auf nas unter //backup sammeln + - (x) TODO: tar syntax (find | py) + - (x) TODO: gpg syntax + - (x) TODO: file handling + - (x) TODO: script (python?) nas-backup weekly 1 -- media/books, media/music/_all + _hoerspiel -> tar, gpg nach //backup - - TODO: s. nas-backup daily +(x) media/books, media/music/_all + _hoerspiel -> tar, gpg nach //backup + (x) TODO: s. nas-backup daily -backup server+nas +logging +- TODO: wo speichern? +- TODO: ggf. lokal und auf NAS kopieren +- TODO: full für alles (taugt nur für auto backup, also ggf. noch ein log) +- TODO: Übersichtliches für die Mail -> Error-Handling! +- TODO: wo und wie sammeln für Mail +- TODO: Mail aus py-script übernehmen + +backup server+nas extern - rsync nas-backup 2x HDD intern (weekly) (5TB?) - TODO: script (python?) mit HD-Erkennung - TODO: zusätzliche HDD @@ -79,8 +50,3 @@ export serien export video - rsync dir 1x 5TB HDD extern - TODO: s. export serien - -**script** - -tar: wo beginnen?, Schleife für dirs - diff --git a/cron.sh b/cron.sh index df9fad3..106d5ac 100755 --- a/cron.sh +++ b/cron.sh @@ -19,4 +19,4 @@ LOG="$1" shift HERE=$(dirname "$0") -$HERE/main.sh -a "$@" >"$LOG" 2>&1 & +$HERE/main.sh "$@" >"$LOG" 2>&1 & diff --git a/hamiller.sh b/hamiller.sh index 1b8cf67..c142285 100755 --- a/hamiller.sh +++ b/hamiller.sh @@ -1,51 +1,34 @@ #!/usr/bin/eval bash -# TODO: cmd line handling -# fn für div. Aktionen (gemeinsame?) +NAS_ROOT=/var/srv/nas/backups BACKUP_ROOT=/var/docker/tmp +NAS_TARGET="$NAS_ROOT/daily/$HOST_NAME/backup.$DAY" -backup_data() { - TARGET_DIR="$BACKUP_ROOT/backup.$DAY" +# +# ACHTUNG: BACKUP_TARGET wird für jeden Lauf _daily1, 2, usw. geköscht, +# es muss sich also für alle _daily?, bzw. _weekly? unterscheiden +# - NAS_ROOT=/var/srv/nas/backups - - LOG_FILE="$NAS_ROOT/log/$HOST_NAME-backup.log" - - log INFO "*** *** Begin hamiller server backup" - delete_dir $TARGET_DIR - check_directory $TARGET_DIR - - # TODO: docker down - - backup_all_dirs "/var" "$TARGET_DIR" # docker - # backup_all_dirs "/var/docker" "$TARGET_DIR" vol tmp - # backup_all_dirs "/var/docker/vol" "$TARGET_DIR" - - # TODO: docker up - - # TODO: copy backup files to NAS - - log INFO "*** End of hamiller server backup" - list_archives $BACKUP_ROOT +backup_daily1() { + BACKUP_SOURCE="/var" + BACKUP_TARGET="$BACKUP_ROOT" + BACKUP_EXCLUDE_DIRS=() } -# TODO: restore fn +copy_to_nas() { + # ins NAS-Verzeichnis verschieben + delete_dir "$NAS_TARGET" + check_dir "$NAS_TARGET" + sudo mv "$BACKUP_ROOT/*" "$NAS_TARGET" +} -while :; do - case $1 in - --daily) - backup_data - break - ;; - --restore) - # TODO - break - ;; - *) # Default case: No more options, so break out of the loop. - break - esac +before_backup() { + run_docker down +} - shift -done +after_backup() { + run_docker up -d + copy_to_nas +} diff --git a/main.inc.sh b/main.inc.sh index bc5419f..c420e7f 100755 --- a/main.inc.sh +++ b/main.inc.sh @@ -5,6 +5,14 @@ PASSPHRASE=1234567890 EXT=tgz.gpg LIST_EXT=txt +# docker compose ausführen +# +# $1 ff. - compose parameter, z.B. up -d +# +run_docker() { + /usr/bin/docker compose -f /var/docker/run/docker-compose.yml --ansi never $@ +} + # check if function $1 exists # # returns true/false @@ -105,10 +113,10 @@ backup_file_prefix() { backup_all_dirs() { local root=$1 local target=$2 + shift 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" @@ -138,6 +146,37 @@ backup_dir() { fi } +## +# auto backup handling +# +# hostname-scripte setzen vars und definieren Funktionen backup_daily1, 2, usw. und backup_weekly1, 2, usw. +# in den Funktionen werden die vars für den einzelnen backup gesetzt (target, excludes, usw.) +# hier wird dann dass hostname-script gesourced (s.o.) und in einer Schleife werden die +# entsprechenden backup_*-Funktionen aufgerufen +# +do_auto_backup() { + local func=$1 + local count=1 + before_backup + while [ $(isFunction $func$count) ]; do + func$count + # vars defined in $func$count in $HOST_NAME.sh + delete_dir "$BACKUP_TARGET" # bei Fehler werden die Dateien hoffentlich überschrieben + check_directory "$BACKUP_TARGET" + backup_all_dirs "$BACKUP_SOURCE" "$BACKUP_TARGET" "${BACKUP_EXCLUDE_DIRS[@]}" + + let "count += 1" + done + after_backup +} +# TODO LOG_FILE="$NAS_ROOT/log/$HOST_NAME-backup-media.log" +backup_daily() { + do_auto_backup backup_daily +} +backup_weekly() { + do_auto_backuo backup_weekly +} + # Inhalt des Archivs in eine Textdatei ausgeben. # # $1 - Archiv diff --git a/main.sh b/main.sh index 28b229b..31890d6 100755 --- a/main.sh +++ b/main.sh @@ -3,27 +3,45 @@ # entrypoint for all actions # - -HERE=$(dirname "$0") -. $HERE/main.inc.sh - - - show_help() { echo "usage: $0 options" - echo " -a, --auto start nightly backup on local machine" + echo " -d, --daily start daily backup on local machine" + echo " -w, --weekly start weekly backup on local machine" echo " --list list archives" echo ' --content ' echo " show contents of archive" echo ' -r, --restore ' echo " restore files from archive to pwd" echo " -h, -?. --help show this help" + echo " " + echo " Script muss auf dem jeweiligen Server ausgeführt werden (ggf. via ssh)." + echo " " } -echo " ### main.sh" +HERE=$(dirname "$0") + +if [ -f $HERE/main.inc.sh ]; then + . $HERE/main.inc.sh +else + echo "**" + echo "** ERROR: Datei \"$HERE/main.inc.sh\" nicht gefunden. " + echo "** Script wird abgebrochen" + echo "**" + show_help + exit 1 +fi + +if [ -f $HERE/$HOST_NAME.sh ]; then + . $HERE/$HOST_NAME.sh +else + echo "**" + echo "** ERROR: Datei \"$HOST_NAME.sh\" nicht gefunden (falscher Rechner?). " + echo "** Script wird abgebrochen." + echo "**" + show_help + exit 2 +fi -# Initialize all the option variables. -# This ensures we are not contaminated by variables from the environment. file= archive= @@ -33,18 +51,24 @@ while :; do show_help # Display a usage synopsis. exit 0 ;; - -a|--auto) - shift - . $HERE/$HOST_NAME.sh "$@" # >$LOGF 2>&1 - break # exit kehrt nicht zu run.sh zurück + -d|--daily) + backup_daily + break + ;; + -w|--weekly) + backup_weekly + break ;; --list) - . $HERE/$HOST_NAME.sh -l + list_archives "$NAS_ROOT/daily/$HOST_NAME" + if [ -d "$NAS_ROOT/weekly/$HOST_NAME" ]; then + list_archives "$NAS_ROOT/weekly/$HOST_NAME" + fi break; ;; --content) if [ "$2" ]; then - . $HERE/$HOST_NAME.sh -c $2 + list_archive_content "$NAS_ROOT" "$2" else echo 'ERROR: "--content" requires a non-empty option argument.' fi @@ -52,10 +76,9 @@ while :; do ;; -r|--restore) if [ "$2" ]; then - echo "not yet implemented" archive=$2 shift - #. $HERE/$HOST_NAME.sh -r $archive $@ + restore "$archive" "$@" else echo 'ERROR: "--restore" requires a non-empty option argument.' fi @@ -94,3 +117,4 @@ while :; do shift done +exit 0 diff --git a/nathan.sh b/nathan.sh index f0257ff..b6e2427 100755 --- a/nathan.sh +++ b/nathan.sh @@ -1,51 +1,49 @@ #!/usr/bin/env bash -# TODO: cmd line handling -# fn für div. Aktionen (gemeinsame?) - - +NAS_ROOT=/var/srv/nas/backups BACKUP_ROOT=/var/docker/tmp +NAS_TARGET="$NAS_ROOT/daily/$HOST_NAME/backup.$DAY" -backup_data() { - TARGET_DIR="$BACKUP_ROOT/backup.$DAY" +# +# ACHTUNG: BACKUP_TARGET wird für jeden Lauf _daily1, 2, usw. geköscht, +# es muss sich also für alle _daily?, bzw. _weekly? unterscheiden +# - NAS_ROOT=/var/srv/nas/backups - - LOG_FILE="$NAS_ROOT/log/$HOST_NAME-backup.log" - - log INFO "*** *** Begin nathan server backup" - delete_dir "$TARGET_DIR" - check_directory "$TARGET_DIR" - - # TODO: docker down - - backup_all_dirs "/var" "$TARGET_DIR" docker - backup_all_dirs "/var/docker" "$TARGET_DIR" vol tmp - backup_all_dirs "/var/docker/vol" "$TARGET_DIR" - - # TODO: docker up - - # TODO: copy backup files to NAS - - log INFO "*** End of nathan server backup" - list_archives $BACKUP_ROOT +backup_daily1() { + BACKUP_SOURCE="/var" + BACKUP_TARGET="$BACKUP_ROOT/var" + BACKUP_EXCLUDE_DIRS=(docker) } -# TODO: restore fn +backup_daily2() { + BACKUP_SOURCE="/var/docker" + BACKUP_TARGET="$BACKUP_ROOT/docker" + BACKUP_EXCLUDE_DIRS=(vol tmp) +} -while :; do - case $1 in - --daily) - backup_data - break - ;; - --restore) - # TODO - break - ;; - *) # Default case: No more options, so break out of the loop. - break - esac +backup_daily3() { + BACKUP_SOURCE="/var/docker/vol" + BACKUP_TARGET="$BACKUP_ROOT/vol" + BACKUP_EXCLUDE_DIRS=() +} - shift -done +copy_to_nas() { + local dir + # einzelne backups iin einem Verzeichnis sammeln + for dir in $(iterate_dirs_in "$BACKUP_ROOT" "$@"); do + sudo mv "$BACKUP_ROOT/$dir/*" .. && rmdir "$BACKUP_ROOT/$dir" + done + # ins NAS-Verzeichnis verschieben + delete_dir "$NAS_TARGET" + check_dir "$NAS_TARGET" + sudo mv "$BACKUP_ROOT/*" "$NAS_TARGET" +} + +before_backup() { + run_docker down +} + +after_backup() { + run_docker up -d + copy_to_nas +} diff --git a/server-backup.code-workspace b/server-backup.code-workspace new file mode 100644 index 0000000..876a149 --- /dev/null +++ b/server-backup.code-workspace @@ -0,0 +1,8 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": {} +} \ No newline at end of file diff --git a/shopts.sh b/shopts.sh deleted file mode 100755 index a2d7407..0000000 --- a/shopts.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/bash -# ex33.sh: Exercising getopts and OPTIND -# Script modified 10/09/03 at the suggestion of Bill Gradwohl. - - -# Here we observe how 'getopts' processes command-line arguments to script. -# The arguments are parsed as "options" (flags) and associated arguments. - -# Try invoking this script with: -# 'scriptname -mn' -# 'scriptname -oq qOption' (qOption can be some arbitrary string.) -# 'scriptname -qXXX -r' -# -# 'scriptname -qr' -#+ - Unexpected result, takes "r" as the argument to option "q" -# 'scriptname -q -r' -#+ - Unexpected result, same as above -# 'scriptname -mnop -mnop' - Unexpected result -# (OPTIND is unreliable at stating where an option came from.) -# -# If an option expects an argument ("flag:"), then it will grab -#+ whatever is next on the command-line. - -NO_ARGS=0 -E_OPTERROR=85 - -if [ $# -eq "$NO_ARGS" ] # Script invoked with no command-line args? -then - echo "Usage: `basename $0` options (-mnopqrs)" - exit $E_OPTERROR # Exit and explain usage. - # Usage: scriptname -options - # Note: dash (-) necessary -fi - - -while getopts ":mnopq:rs" Option -do - case $Option in - m ) echo "$OPTIND -$Option ($OPTARG)";; - n | o ) echo "$OPTIND -$Option ($OPTARG)";; - p ) echo "$OPTIND -$Option ($OPTARG)";; - q ) echo "$OPTIND -$Option ($OPTARG)";; - # Note that option 'q' must have an associated argument, - #+ otherwise it falls through to the default. - r | s ) echo "$OPTIND -$Option ($OPTARG)";; - * ) echo "Unimplemented option chosen.";; # Default. - esac -done - -shift $(($OPTIND - 1)) -echo "Rest $@" - -# Decrements the argument pointer so it points to next argument. -# $1 now references the first non-option item supplied on the command-line -#+ if one exists. - -exit $? - -# As Bill Gradwohl states, -# "The getopts mechanism allows one to specify: scriptname -mnop -mnop -#+ but there is no reliable way to differentiate what came -#+ from where by using OPTIND." -# There are, however, workarounds. \ No newline at end of file diff --git a/synology.sh b/synology.sh index 05b10ee..e23990c 100755 --- a/synology.sh +++ b/synology.sh @@ -1,96 +1,33 @@ #!/usr/bin/eval bash -# TODO: cmd line handling -# fn für div. Aktionen (gemeinsame?) - NAS_ROOT=/volume1/nfs/backups -backup_media() { - TARGET_DIR="$NAS_ROOT/weekly/$HOST_NAME" - - LOG_FILE="$NAS_ROOT/log/$HOST_NAME-backup-media.log" - - log INFO "*** *** Begin NAS backup (media/books, media/music)" - - 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 $TARGET_DIR +# +# ACHTUNG: BACKUP_TARGET wird für jeden Lauf _daily1, 2, usw. geköscht, +# es muss sich also für alle _daily?, bzw. _weekly? unterscheiden +# +backup_daily1() { + BACKUP_SOURCE="/volume1/data" + BACKUP_TARGET="$NAS_ROOT/daily/$HOST_NAME/backup.$DAY/data" + BACKUP_EXCLUDE_DIRS=("@eaDir" "Temporary Items" "lost+found") +} +backup_daily2() { + BACKUP_SOURCE="/volume1/nfs" + BACKUP_TARGET="$NAS_ROOT/daily/$HOST_NAME/backup.$DAY/nfs" + BACKUP_EXCLUDE_DIRS=("@eaDir" "Temporary Items" "lost+found" backups) } -backup_data() { - - TARGET_DIR="$NAS_ROOT/daily/$HOST_NAME/backup.$DAY" - - LOG_FILE="$NAS_ROOT/log/$HOST_NAME-backup.log" - - log INFO "*** *** Begin NAS backup (data, nfs)" - 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[@]}" - - log INFO "*** End of NAS backup" - list_archives $TARGET_DIR +backup_weekly1() { + BACKUP_SOURCE="/volume1/media" + BACKUP_TARGET="$NAS_ROOT/weekly/$HOST_NAME" + BACKUP_EXCLUDE_DIRS=("@eaDir" "Temporary Items" "lost+found" serien tmp video "video.archive") } -# TODO: restore fn +before_backup() { + # nothing to do +} - -## -# auto backup handling -# -# hostname-scripte setzen vars und definieren Funktionen backup_daily1, 2, usw. und backup_weekly1, 2, usw. -# in den Funktionen werden die vars für den einzelnen backuü gesetzt (target, excludes, usw.) -# im main-script wird dann dass hostname-script gesourced und in einer Schleife werden die -# entsprechenden backup_*-Funktionen aufgerufen -# -# count=1 -# while [ $(isFunction backup_daily$count) ]; do -# backup_daily$count # setzt die nötigen vars für den backup -# do_backup "daily" -# let "count += 1" -# done -# - -while :; do - case $1 in - --daily) - backup_data - break - ;; - --weekly) - backup_media - break - ;; - -l|--list) - list_archives "$NAS_ROOT" - break; - ;; - -c|--content) - if [ "$2" ]; then - list_archive_content "$NAS_ROOT" "$2" - else - echo 'ERROR: "--content" requires a non-empty option argument.' - fi - break - ;; - --restore) - # TODO - break - ;; - *) # Default case: No more options, so break out of the loop. - break - esac - - shift -done +after_backup() { + # nothing to do +} diff --git a/test.sh b/test.sh index ccfeb12..8f45879 100755 --- a/test.sh +++ b/test.sh @@ -1,274 +1,11 @@ #!/usr/bin/env bash -HOST_NAME=$(hostname) -DAY=$(date +%u) HERE=$(dirname "$0") -PASSPHRASE=1234567890 -EXT=tgz.gpg +. $HERE/main.inc.sh - -# 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 -} +# nicht auf calvados +#. $HERE/$HOST_NAME test() { for i in "$@"; do echo "$i"; done @@ -296,42 +33,7 @@ list2() { #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 - +EXC=() +iterate_dirs_in "." ${EXC[@]} 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 diff --git a/test/main.inc b/test/main.inc deleted file mode 100755 index cf1e801..0000000 --- a/test/main.inc +++ /dev/null @@ -1,8 +0,0 @@ - -INC=include -HOST_NAME=$(hostname) - -testfunc() { - echo "testfunc() works!" -} - \ No newline at end of file diff --git a/test/main.sh b/test/main.sh deleted file mode 100755 index 8fe24cc..0000000 --- a/test/main.sh +++ /dev/null @@ -1,88 +0,0 @@ -#!/usr/bin/env bash - -show_help() { - echo "usage: $0 options" - echo " -a, --auto start nightly backup" - echo " -l, --list list archives" - echo ' -c, --content ' - echo " show contents of archive" - echo ' -r, --restore ' - echo " restore files from archive to pwd" - echo " -h, -?. --help show this help" -} - -echo " ### main.sh" - -# Initialize all the option variables. -# This ensures we are not contaminated by variables from the environment. -file= -archive= - -while :; do - case $1 in - -h|-\?|--help) - show_help # Display a usage synopsis. - exit 0 - ;; - -a|--auto) - shift - . $HERE/$HOST_NAME.sh "$@" >$LOGF 2>&1 - break # exit kehrt nicht zu run.sh zurück - ;; - -l|--list) - . $HERE/$HOST_NAME.sh -l - break; - ;; - -c|--content) - if [ "$2" ]; then - echo "not yet implemented" - #. $HERE/$HOST_NAME.sh -c $2 - else - echo 'ERROR: "--content" requires a non-empty option argument.' - fi - break - ;; - -r|--restore) - if [ "$2" ]; then - echo "not yet implemented" - archive=$2 - shift - #. $HERE/$HOST_NAME.sh -r $archive $@ - else - echo 'ERROR: "--restore" requires a non-empty option argument.' - fi - break - ;; - - # --- example -> https://mywiki.wooledge.org/BashFAQ/035 - -f|--file) # Takes an option argument; ensure it has been specified. - if [ "$2" ]; then - file=$2 - shift - else - die 'ERROR: "--file" requires a non-empty option argument.' - fi - ;; - --file=?*) - file=${1#*=} # Delete everything up to "=" and assign the remainder. - ;; - --file=) # Handle the case of an empty --file= - die 'ERROR: "--file" requires a non-empty option argument.' - ;; - --) # End of all options. - shift - break - ;; - -?*) - echo "WARN: Unknown option (ignored): $1" - echo - show_help - exit - ;; - *) # Default case: No more options, so break out of the loop. - break - esac - - shift -done - diff --git a/test/nathan.sh b/test/nathan.sh deleted file mode 100755 index bbe6e69..0000000 --- a/test/nathan.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -echo " *** nathan.sh" -for i in "$@"; do echo "param: $i"; done - -echo " include=$INC" -echo " host=$HOST_NAME" -testfunc -echo " *** nathan.sh end" - diff --git a/test/run.sh b/test/run.sh deleted file mode 100755 index 33d6dc3..0000000 --- a/test/run.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash -HERE=$(dirname "$0") -. $HERE/main.inc - -LOGF=$HERE/t1.log - -echo "--- run.sh" - -. $HERE/main.sh "$@" - -echo "--- run.sh end" diff --git a/test/t1.log b/test/t1.log deleted file mode 100644 index e23e4a3..0000000 --- a/test/t1.log +++ /dev/null @@ -1,10 +0,0 @@ -testfunc() works! - ### main.sh -usage: ./run.sh options - -a, --auto start nightly backup - -l, --list list archives - -c, --content - show contents of archive - -r, --restore - restore files from archive to pwd - -h, -?. --help show this help