backup.sh script hinzugefuegt
This commit is contained in:
230
backup.sh
Normal file
230
backup.sh
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
############################
|
||||||
|
# Konfiguration
|
||||||
|
############################
|
||||||
|
|
||||||
|
SFTP_SERVER="sftp.domain.tld"
|
||||||
|
SFTP_PORT="22"
|
||||||
|
SFTP_USER="sftp-user"
|
||||||
|
SFTP_PASS="passw0rd"
|
||||||
|
REMOTE_DIR="/uploads"
|
||||||
|
|
||||||
|
EMAIL=""
|
||||||
|
|
||||||
|
############################
|
||||||
|
# Basis
|
||||||
|
############################
|
||||||
|
|
||||||
|
HOSTNAME=$(hostname)
|
||||||
|
DATE=$(date "+%Y-%m-%d_%H-%M")
|
||||||
|
|
||||||
|
BACKUP_DIR="/backups/docker"
|
||||||
|
LOG_DIR="/var/log/script-logs"
|
||||||
|
|
||||||
|
mkdir -p "$BACKUP_DIR" "$LOG_DIR"
|
||||||
|
|
||||||
|
PROJECT_NAME=""
|
||||||
|
ARCHIVE_FILE=""
|
||||||
|
LOG_FILE=""
|
||||||
|
|
||||||
|
############################
|
||||||
|
# Mail Funktion
|
||||||
|
############################
|
||||||
|
send_mail() {
|
||||||
|
STATUS="$1"
|
||||||
|
SUBJECT="[$HOSTNAME] Docker Backup $STATUS ($PROJECT_NAME)"
|
||||||
|
|
||||||
|
if command -v mail >/dev/null 2>&1; then
|
||||||
|
mail -s "$SUBJECT" "$EMAIL" -A "$LOG_FILE" <<EOF
|
||||||
|
Docker Backup Status: $STATUS
|
||||||
|
|
||||||
|
Host: $HOSTNAME
|
||||||
|
Projekt: $PROJECT_NAME
|
||||||
|
Datum: $DATE
|
||||||
|
Archiv: $ARCHIVE_FILE
|
||||||
|
|
||||||
|
Logfile im Anhang.
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
echo "Mail nicht installiert – übersprungen."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
############################
|
||||||
|
# Fehlerbehandlung
|
||||||
|
############################
|
||||||
|
error_handler() {
|
||||||
|
echo "FEHLER aufgetreten!"
|
||||||
|
send_mail "FEHLER"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
trap error_handler ERR
|
||||||
|
|
||||||
|
############################
|
||||||
|
# Compose Projekte
|
||||||
|
############################
|
||||||
|
|
||||||
|
echo "Verfügbare Docker Compose Projekte:"
|
||||||
|
|
||||||
|
mapfile -t PROJECTS < <(
|
||||||
|
docker ps --format '{{.Label "com.docker.compose.project"}}' \
|
||||||
|
| sort -u \
|
||||||
|
| grep -v '^$'
|
||||||
|
)
|
||||||
|
|
||||||
|
if [[ ${#PROJECTS[@]} -eq 0 ]]; then
|
||||||
|
echo "Keine Compose-Projekte gefunden."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
for i in "${!PROJECTS[@]}"; do
|
||||||
|
echo "[$((i+1))] ${PROJECTS[$i]}"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
read -p "Projekt auswählen (Nummer): " SELECTION
|
||||||
|
|
||||||
|
if ! [[ "$SELECTION" =~ ^[0-9]+$ ]] || (( SELECTION < 1 || SELECTION > ${#PROJECTS[@]} )); then
|
||||||
|
echo "Ungültige Auswahl."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
PROJECT_NAME="${PROJECTS[$((SELECTION-1))]}"
|
||||||
|
LOG_FILE="$LOG_DIR/docker-backup-${PROJECT_NAME}.log"
|
||||||
|
|
||||||
|
exec > >(tee -a "$LOG_FILE") 2>&1
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "===== Backup gestartet ====="
|
||||||
|
echo "Projekt : $PROJECT_NAME"
|
||||||
|
echo "Host : $HOSTNAME"
|
||||||
|
echo "Datum : $DATE"
|
||||||
|
echo
|
||||||
|
|
||||||
|
############################
|
||||||
|
# Container sammeln
|
||||||
|
############################
|
||||||
|
|
||||||
|
mapfile -t CONTAINERS < <(
|
||||||
|
docker ps \
|
||||||
|
--filter "label=com.docker.compose.project=$PROJECT_NAME" \
|
||||||
|
--format '{{.Names}}'
|
||||||
|
)
|
||||||
|
|
||||||
|
echo "Container im Stack:"
|
||||||
|
printf ' - %s\n' "${CONTAINERS[@]}"
|
||||||
|
echo
|
||||||
|
|
||||||
|
############################
|
||||||
|
# Mounts sammeln
|
||||||
|
############################
|
||||||
|
|
||||||
|
MOUNTS=()
|
||||||
|
|
||||||
|
for c in "${CONTAINERS[@]}"; do
|
||||||
|
mapfile -t PATHS < <(
|
||||||
|
docker inspect "$c" \
|
||||||
|
| jq -r '.[0].Mounts[] | select(.Type=="volume" or .Type=="bind") | .Source'
|
||||||
|
)
|
||||||
|
|
||||||
|
for p in "${PATHS[@]}"; do
|
||||||
|
[[ -d "$p" ]] && MOUNTS+=("$p")
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
mapfile -t MOUNTS < <(printf "%s\n" "${MOUNTS[@]}" | sort -u)
|
||||||
|
|
||||||
|
if [[ ${#MOUNTS[@]} -eq 0 ]]; then
|
||||||
|
echo "Keine gültigen Mounts gefunden."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
############################
|
||||||
|
# Stack stoppen
|
||||||
|
############################
|
||||||
|
|
||||||
|
echo "Stoppe Stack..."
|
||||||
|
docker stop "${CONTAINERS[@]}" >/dev/null
|
||||||
|
sleep 3
|
||||||
|
|
||||||
|
############################
|
||||||
|
# Daten kopieren
|
||||||
|
############################
|
||||||
|
|
||||||
|
TMP_DIR="/tmp/docker-backup-$PROJECT_NAME"
|
||||||
|
rm -rf "$TMP_DIR"
|
||||||
|
mkdir -p "$TMP_DIR"
|
||||||
|
|
||||||
|
echo "Kopiere Daten..."
|
||||||
|
|
||||||
|
for mount in "${MOUNTS[@]}"; do
|
||||||
|
BASENAME=$(basename "$mount")
|
||||||
|
rsync -a "$mount/" "$TMP_DIR/$BASENAME/"
|
||||||
|
done
|
||||||
|
|
||||||
|
############################
|
||||||
|
# ZIP Archiv erstellen
|
||||||
|
############################
|
||||||
|
|
||||||
|
ARCHIVE_FILE="$BACKUP_DIR/${HOSTNAME}-${PROJECT_NAME}-${DATE}.zip"
|
||||||
|
|
||||||
|
echo "Erstelle ZIP Archiv..."
|
||||||
|
|
||||||
|
TOTAL_SIZE=$(du -sb "$TMP_DIR" | awk '{print $1}')
|
||||||
|
|
||||||
|
(
|
||||||
|
cd "$TMP_DIR"
|
||||||
|
zip -r -q - .
|
||||||
|
) | pv -s "$TOTAL_SIZE" > "$ARCHIVE_FILE"
|
||||||
|
|
||||||
|
echo "Archiv erstellt: $ARCHIVE_FILE"
|
||||||
|
|
||||||
|
############################
|
||||||
|
# Stack starten
|
||||||
|
############################
|
||||||
|
|
||||||
|
echo "Starte Stack..."
|
||||||
|
docker start "${CONTAINERS[@]}" >/dev/null
|
||||||
|
echo "Stack läuft wieder."
|
||||||
|
|
||||||
|
############################
|
||||||
|
# Optionaler Upload
|
||||||
|
############################
|
||||||
|
|
||||||
|
echo
|
||||||
|
read -p "Backup zum SFTP hochladen? (j/n): " DO_UPLOAD
|
||||||
|
|
||||||
|
if [[ "$DO_UPLOAD" == "j" ]]; then
|
||||||
|
|
||||||
|
if [[ -z "$SFTP_PASS" ]]; then
|
||||||
|
read -s -p "SFTP Passwort eingeben: " SFTP_PASS
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Starte Upload..."
|
||||||
|
|
||||||
|
sshpass -p "$SFTP_PASS" \
|
||||||
|
scp -P "$SFTP_PORT" "$ARCHIVE_FILE" \
|
||||||
|
"$SFTP_USER@$SFTP_SERVER:$REMOTE_DIR/"
|
||||||
|
|
||||||
|
echo "Upload abgeschlossen."
|
||||||
|
fi
|
||||||
|
|
||||||
|
############################
|
||||||
|
# Cleanup
|
||||||
|
############################
|
||||||
|
|
||||||
|
rm -rf "$TMP_DIR"
|
||||||
|
|
||||||
|
echo "Backup erfolgreich abgeschlossen."
|
||||||
|
|
||||||
|
send_mail "ERFOLGREICH"
|
||||||
|
|
||||||
|
echo "===== Fertig ====="
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user