auto-backup-Mimik steht
This commit is contained in:
1 parent
1fcdb5669a
commit
22d9442b42
17 files changed
+223
-738
No files matched your search
@@ -12,3 +12,4 @@
|
||||
# Built Visual Studio Code Extensions
|
||||
*.vsix
|
||||
|
||||
._server-backup.code-workspace
|
||||
@@ -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/<hostname>/
|
||||
```
|
||||
@@ -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
|
||||
|
||||
@@ -19,4 +19,4 @@ LOG="$1"
|
||||
shift
|
||||
|
||||
HERE=$(dirname "$0")
|
||||
$HERE/main.sh -a "$@" >"$LOG" 2>&1 &
|
||||
$HERE/main.sh "$@" >"$LOG" 2>&1 &
|
||||
+23
-40
@@ -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
|
||||
}
|
||||
+40
-1
@@ -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
|
||||
|
||||
@@ -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 <archive> '
|
||||
echo " show contents of archive"
|
||||
echo ' -r, --restore <archive> <file(s)> '
|
||||
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
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"settings": {}
|
||||
}
|
||||
@@ -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.
|
||||
+23
-86
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
@@ -1,8 +0,0 @@
|
||||
|
||||
INC=include
|
||||
HOST_NAME=$(hostname)
|
||||
|
||||
testfunc() {
|
||||
echo "testfunc() works!"
|
||||
}
|
||||
|
||||
@@ -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 <archive> '
|
||||
echo " show contents of archive"
|
||||
echo ' -r, --restore <archive> <file(s)> '
|
||||
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
|
||||
|
||||
@@ -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"
|
||||
|
||||
-11
@@ -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"
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
testfunc() works!
|
||||
### main.sh
|
||||
usage: ./run.sh options
|
||||
-a, --auto start nightly backup
|
||||
-l, --list list archives
|
||||
-c, --content <archive>
|
||||
show contents of archive
|
||||
-r, --restore <archive> <file(s)>
|
||||
restore files from archive to pwd
|
||||
-h, -?. --help show this help
|
||||
Reference in new issue
Block a user