Update external-backup.sh

This commit is contained in:
Tobias Strobel 2021-08-12 17:44:15 +02:00
parent dc9985bed3
commit 4bbff4ba6f

View file

@ -1,16 +1,16 @@
#!/bin/bash #!/bin/bash
# #
# Script zieht per rsync Backups und rotiert Backup-Verzeichnisse # Script rotiert Backup-Verzeichnisse und zieht per rsync Backups
# http://www.heinlein-support.de
# #
# https://www.heinlein-support.de/howto/backups-und-snapshots-von-linux-servern-mit-rsync-und-ssh # https://www.heinlein-support.de/howto/backups-und-snapshots-von-linux-servern-mit-rsync-und-ssh
# #
# Zusammengeführt und angepasst durch Tobias Strobel (2021) # Zusammengeführt und angepasst durch Tobias Strobel (2021)
# #
RDIFFEXIT="$(mktemp)" LOGFILE="$(mktemp)"
GOTIFYURL="https://push.strobeto.de/message?token=Anks7VaBnyf7jCB" GOTIFYURL="https://push.strobeto.de/message?token=Anks7VaBnyf7jCB"
HCBACKUPURL="https://hc.strobeto.de/ping/375f20ea-aaa7-4b34-b279-bafc3ff55fed" HCURL="https://hc.strobeto.de/ping/615c0b9b-077d-46b4-913b-b70d911dab27"
HCROTATEURL="https://hc.strobeto.de/ping/f169adf0-a1b3-4823-8fb6-f3a63546bb42"
SERVER="$(hostname)" SERVER="$(hostname)"
@ -39,26 +39,23 @@ clearLED () {
finishUp () { finishUp () {
# Clean up tempfiles # Clean up tempfiles
rm "$RDIFFEXIT" rm "$LOGFILE"
# Just to be sure
sync -f $DATA_PATH sync -f $DATA_PATH
} }
healthchecksStart () { healthchecksStart () {
# $1 Healthchecks URL curl -fsS -m 10 --retry 5 -o /dev/null "$HCURL"/start
curl -fsS -m 10 --retry 5 -o /dev/null "$1"/start
} }
healthchecksFinish () { healthchecksFinish () {
# $1 Healthchecks URL # $1 Status Code
# $2 Status Code curl -fsS -m 10 --retry 5 -o /dev/null --data-binary "@$LOGFILE" "$HCURL"/"$1"
# $3 Logs
curl -fsS -m 10 --retry 5 --data-raw "$3" "$1"/"$2"
} }
notify () { notify () {
# $1 Action # $1 Action
# $2 Last command succeeded # $2 Status code
# $3 Custom Title # $3 Custom Title
# $4 Custom Message # $4 Custom Message
# $5 Custom Priority # $5 Custom Priority
@ -67,38 +64,20 @@ notify () {
NOTIFY_PRIORITY=1 NOTIFY_PRIORITY=1
case "$1" in case "$1" in
rotate-start) start)
NOTIFY_TITLE+="Rotation started"
NOTIFY_MESSAGE="Rotation on external hdd started"
;;
rotate-end)
if [ "$2" -eq 0 ]; then
NOTIFY_TITLE+="Rotation finished"
NOTIFY_MESSAGE="Rotation on external hdd finished"
NOTIFY_PRIORITY=5
else
NOTIFY_TITLE+="Rotation has ERRORS"
NOTIFY_MESSAGE="Exit code $STATUSCODE. See logs attached to healthchecks for more information."
NOTIFY_PRIORITY=8
fi
;;
backup-start)
NOTIFY_TITLE+="Backup started" NOTIFY_TITLE+="Backup started"
NOTIFY_MESSAGE="Backup to external hdd started" NOTIFY_MESSAGE="Backup to external hdd started"
;; ;;
backup-end) finish)
if [ "$2" -eq 0 ]; then NOTIFY_TITLE+="Backup finished"
NOTIFY_TITLE+="Backup finished" NOTIFY_MESSAGE="Backup to external hdd finished"
NOTIFY_MESSAGE="Backup to external hdd finished" NOTIFY_PRIORITY=5
NOTIFY_PRIORITY=5 ;;
else error)
NOTIFY_TITLE+="Backup has ERRORS" NOTIFY_TITLE+="Backup has ERRORS"
NOTIFY_MESSAGE="Exit code $STATUSCODE. See logs attached to healthchecks for more information." NOTIFY_MESSAGE="Exit code $STATUSCODE. See logs attached to healthchecks for more information."
NOTIFY_PRIORITY=8 NOTIFY_PRIORITY=8
fi
;; ;;
*) *)
NOTIFY_TITLE+="$3" NOTIFY_TITLE+="$3"
@ -107,7 +86,7 @@ notify () {
;; ;;
esac esac
curl "$GOTIFYURL" -F "title=$NOTIFY_TITLE" -F "message=$NOTIFY_MESSAGE" -F "priority=$NOTIFY_PRIORITY" curl -fsS -m 10 --retry 5 -o /dev/null "$GOTIFYURL" -F "title=$NOTIFY_TITLE" -F "message=$NOTIFY_MESSAGE" -F "priority=$NOTIFY_PRIORITY"
} }
checkFreeSpace () { checkFreeSpace () {
@ -118,7 +97,8 @@ INODEISFREE=$(df -i /$DATA_PATH | tail -n1 | sed -e "$GETPERCENTAGE")
if [ "$KBISFREE" -ge $HDMINFREE ] || [ "$INODEISFREE" -ge $HDMINFREE ] ; then if [ "$KBISFREE" -ge $HDMINFREE ] || [ "$INODEISFREE" -ge $HDMINFREE ] ; then
echo "Fatal: Not enough space left for rotating backups!" echo "Fatal: Not enough space left for rotating backups!"
logger "Fatal: Not enough space left for rotating backups!" healthchecksFinish fail
notify custom "NOT_ENOUGH_SPACE_LEFT" "FATAL" "Not enough space left for rotating backups!"
exit exit
fi fi
} }
@ -126,7 +106,8 @@ fi
basicChecks () { basicChecks () {
if ! [ -d $DATA_PATH ] ; then if ! [ -d $DATA_PATH ] ; then
echo "Fatal: Data path does not exist: $DATA_PATH" echo "Fatal: Data path does not exist: $DATA_PATH"
logger "Fatal: Data path does not exist: $DATA_PATH" healthchecksFinish fail
notify custom "DATA_PATH_NON_EXISTENT" "FATAL" "Data path does not exist: $DATA_PATH"
exit exit
fi fi
@ -134,14 +115,12 @@ basicChecks () {
# Ggf. Verzeichnis anlegen # Ggf. Verzeichnis anlegen
if ! [ -d $DATA_PATH/"$SERVER"/daily.0 ] ; then if ! [ -d $DATA_PATH/"$SERVER"/daily.0 ] ; then
mkdir -p $DATA_PATH/"$SERVER"/daily.0 mkdir -p $DATA_PATH/"$SERVER"/daily.0
fi fi
} }
rotate () { rotate () {
echo "Rotating snapshots of $SERVER..." echo "Rotating snapshots of $SERVER..."
healthchecksStart $HCROTATEURL
notify rotate-start
# Das hoechste Snapshot abloeschen # Das hoechste Snapshot abloeschen
if [ -d $DATA_PATH/"$SERVER"/daily.7 ] ; then if [ -d $DATA_PATH/"$SERVER"/daily.7 ] ; then
@ -149,9 +128,9 @@ rotate () {
fi fi
# Alle anderen Snapshots eine Nummer nach oben verschieben # Alle anderen Snapshots eine Nummer nach oben verschieben
for OLD in 6 5 4 3 2 1 ; do for OLD in 12 11 10 9 8 7 6 5 4 3 2 1 ; do
if [ -d $DATA_PATH/"$SERVER"/daily.$OLD ] ; then if [ -d $DATA_PATH/"$SERVER"/daily.$OLD ] ; then
NEW=$($OLD + 1) NEW=$(( OLD + 1 ))
# Datum sichern # Datum sichern
touch $DATA_PATH/.timestamp -r $DATA_PATH/"$SERVER"/daily.$OLD touch $DATA_PATH/.timestamp -r $DATA_PATH/"$SERVER"/daily.$OLD
mv $DATA_PATH/"$SERVER"/daily.$OLD $DATA_PATH/"$SERVER"/daily."$NEW" mv $DATA_PATH/"$SERVER"/daily.$OLD $DATA_PATH/"$SERVER"/daily."$NEW"
@ -162,50 +141,62 @@ rotate () {
# Snapshot von Level-0 per hardlink-Kopie nach Level-1 kopieren # Snapshot von Level-0 per hardlink-Kopie nach Level-1 kopieren
if [ -d $DATA_PATH/"$SERVER"/daily.0 ] ; then if [ -d $DATA_PATH/"$SERVER"/daily.0 ] ; then
ROTATELOG=$(cp -al $DATA_PATH/"$SERVER"/daily.0 $DATA_PATH/"$SERVER"/daily.1; echo $? > "$RDIFFEXIT") cp -al $DATA_PATH/"$SERVER"/daily.0 $DATA_PATH/"$SERVER"/daily.1
fi fi
STATUSCODE=$(cat "$RDIFFEXIT") STATUSCODE=$?
if [ "$STATUSCODE" -ne 0 ] ; then
echo "Fatal: rotation finished on $SERVER with errors!"
healthchecksFinish "$STATUSCODE"
notify error "$STATUSCODE"
exit "$STATUSCODE"
fi
echo "Finished rotating backups of $SERVER..." echo "Finished rotating backups of $SERVER..."
healthchecksFinish $HCROTATEURL "$STATUSCODE" "$ROTATELOG" healthchecksFinish "$STATUSCODE"
notify rotate-end "$STATUSCODE" notify error "$STATUSCODE"
} }
backup () { backup () {
# Los geht`s: rsync zieht ein Vollbackup
echo "Starting rsync backup from $SERVER..." echo "Starting rsync backup from $SERVER..."
healthchecksStart $HCBACKUPURL
notify backup-start
BACKUPLOG=$(rsync -avz --numeric-ids -e ssh --delete --delete-excluded \ rsync -aAXHh --stats --numeric-ids --noatime --delete --delete-excluded \
--include={"/mnt/storage/nc_data","/mnt/storage/media","/mnt/storage/backup"} \ --include={"/mnt/storage","/mnt/storage/nc_data**","/mnt/storage/media**","/mnt/storage/backup**"} \
--exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found","/.snapshots"} \ --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found","/.snapshots"} \
$SRC_PATH $DATA_PATH/"$SERVER"/daily.0 \ $SRC_PATH $DATA_PATH/"$SERVER"/daily.0
; echo $? > "$RDIFFEXIT")
STATUSCODE=$(cat "$RDIFFEXIT") STATUSCODE=$?
# Rückgabewert prüfen. # Rückgabewert prüfen.
# 0 = fehlerfrei, # 0 = fehlerfrei,
# 24 ist harmlos; tritt auf, wenn während der Laufzeit # 24 ist harmlos; tritt auf, wenn während der Laufzeit
# von rsync noch (/tmp?) Dateien verändert oder gelöscht wurden. # von rsync noch (/tmp?) Dateien verändert oder gelöscht wurden.
# Alles andere ist fatal -- siehe man (1) rsync # Alles andere ist fatal -- siehe man (1) rsync
if ! [ "$STATUSCODE" = 24 ] || ! [ "$STATUSCODE" = 0 ] ; then if [ "$STATUSCODE" -ne 24 ] && [ "$STATUSCODE" -ne 0 ] ; then
echo "Fatal: rsync finished $SERVER with errors!" echo "Fatal: rsync finished on $SERVER with errors!"
healthchecksFinish "$STATUSCODE"
notify error "$STATUSCODE"
exit "$STATUSCODE"
fi fi
# Verzeichnis anfassen, um Backup-Datum zu speichern # Verzeichnis anfassen, um Backup-Datum zu speichern
touch $DATA_PATH/"$SERVER"/daily.0 touch $DATA_PATH/"$SERVER"/daily.0
echo "Finished rsync backup from $SERVER..." echo "Finished rsync backup from $SERVER..."
healthchecksFinish $HCBACKUPURL "$STATUSCODE" "$BACKUPLOG"
notify backup-end "$STATUSCODE"
} }
# Write output to logfile
exec > >(tee -i "${LOGFILE}")
exec 2>&1
healthchecksStart
notify start
setLED setLED
basicChecks basicChecks
backup backup
rotate rotate
healthchecksFinish
notify finish 0
finishUp finishUp
clearLED clearLED