initial, doku folgt.
This commit is contained in:
parent
7dabd88eaf
commit
8e9b7c932a
@ -1,8 +1,4 @@
|
||||
# template_repository
|
||||
|
||||
|
||||
|
||||
Wichtig: Link für Lizenz anpassen.
|
||||
### Doku folgt.
|
||||
|
||||
|
||||
|
||||
@ -11,5 +7,5 @@ Wichtig: Link für Lizenz anpassen.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<img src="https://assets.techniverse.net/f1/logos/small/license.png" alt="License" width="15" height="15"> <a href="./template_repository/src/branch/main/LICENSE">License</a> | <img src="https://assets.techniverse.net/f1/logos/small/matrix2.svg" alt="Matrix" width="15" height="15"> <a href="https://matrix.to/#/#community:techniverse.net">Matrix</a> | <img src="https://assets.techniverse.net/f1/logos/small/mastodon2.svg" alt="Matrix" width="15" height="15"> <a href="https://social.techniverse.net/@donnerwolke">Mastodon</a>
|
||||
<img src="https://assets.techniverse.net/f1/logos/small/license.png" alt="License" width="15" height="15"> <a href="./pbs-backup-client-script/src/branch/main/LICENSE">License</a> | <img src="https://assets.techniverse.net/f1/logos/small/matrix2.svg" alt="Matrix" width="15" height="15"> <a href="https://matrix.to/#/#community:techniverse.net">Matrix</a> | <img src="https://assets.techniverse.net/f1/logos/small/mastodon2.svg" alt="Matrix" width="15" height="15"> <a href="https://social.techniverse.net/@donnerwolke">Mastodon</a>
|
||||
</p>
|
66
v1/pbs-backup.v1.sh
Normal file
66
v1/pbs-backup.v1.sh
Normal file
@ -0,0 +1,66 @@
|
||||
#!/bin/bash
|
||||
# Script Name: pbs-backup.v1.sh
|
||||
# Beschreibung: Erstellt Backups auf einem PBS
|
||||
# Aufruf: ./pbs-backup-script.v1_msmtp.sh
|
||||
# Autor: Patrick Asmus
|
||||
# Web: https://www.techniverse.net
|
||||
# Git-Reposit.: ssh://git@git.techniverse.net:10022/internal-infrastructure/pbs-backup-scripts.git
|
||||
# Version: 1.1
|
||||
# Datum: 13.09.2024
|
||||
# Modifikation: added email support
|
||||
#####################################################
|
||||
|
||||
# Variablen
|
||||
HOSTNAME="$(hostname)"
|
||||
|
||||
export PBS_REPOSITORY=""
|
||||
export PBS_PASSWORD=""
|
||||
export PBS_FINGERPRINT=""
|
||||
|
||||
MAIL_RECIPIENTS=""
|
||||
MAIL_NOTIFY_ON_SUCCESS=true
|
||||
MAIL_SUBJECT_SUCCESS=" ${HOSTNAME} | Backup erfolgreich abgeschlossen"
|
||||
MAIL_SUBJECT_FAILURE=" ${HOSTNAME} | Fehler beim Backup"
|
||||
|
||||
LOGFILE=$(mktemp)
|
||||
|
||||
# Verzeichnisse, die gesichert werden sollen
|
||||
INCLUDE_DIRS=(
|
||||
"/root"
|
||||
"/home"
|
||||
"/var/lib/docker/volumes/"
|
||||
)
|
||||
|
||||
BACKUP_COMMAND="proxmox-backup-client backup"
|
||||
|
||||
for dir in "${INCLUDE_DIRS[@]}"; do
|
||||
dir_name=$(basename "$dir")
|
||||
BACKUP_COMMAND+=" ${dir_name}.pxar:${dir}"
|
||||
done
|
||||
|
||||
echo "Starte das Backup..."
|
||||
eval "$BACKUP_COMMAND" &> "$LOGFILE"
|
||||
|
||||
# Überprüfen, ob das Backup erfolgreich war
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "Backup erfolgreich abgeschlossen." | tee -a "$LOGFILE"
|
||||
if [ "$MAIL_NOTIFY_ON_SUCCESS" = true ]; then
|
||||
{
|
||||
echo "Das Backup wurde erfolgreich abgeschlossen."
|
||||
echo ""
|
||||
echo "Ausgabe des Backups:"
|
||||
cat "$LOGFILE"
|
||||
} | mail -s "$MAIL_SUBJECT_SUCCESS" $MAIL_RECIPIENTS
|
||||
fi
|
||||
else
|
||||
echo "Fehler beim Backup." | tee -a "$LOGFILE"
|
||||
{
|
||||
echo "Es ist ein Fehler beim Backup aufgetreten."
|
||||
echo ""
|
||||
echo "Ausgabe des Backups:"
|
||||
cat "$LOGFILE"
|
||||
} | mail -s "$MAIL_SUBJECT_FAILURE" $MAIL_RECIPIENTS
|
||||
fi
|
||||
|
||||
# Temporäre Datei löschen
|
||||
rm "$LOGFILE"
|
40
v2/pbs-backup.v2.conf
Normal file
40
v2/pbs-backup.v2.conf
Normal file
@ -0,0 +1,40 @@
|
||||
# --- PBS --- #
|
||||
# PBS_FINGERPRINT ist OPTIONAL und nur bei selbstsigniertem Zertifikat nötig.
|
||||
export PBS_REPOSITORY=""
|
||||
export PBS_FINGERPRINT=""
|
||||
PBS_API=""
|
||||
|
||||
# --- Quellen (Array!) --- #
|
||||
INCLUDE_DIRS=(
|
||||
"/home/"
|
||||
"/root/"
|
||||
"/etc"
|
||||
)
|
||||
|
||||
# --- Logging & Lock --- #
|
||||
LOGFILE="/var/log/pbs-backup.v2.log"
|
||||
LOCKFILE="/var/lock/pbs-backup.v2.lock"
|
||||
|
||||
# --- Mail --- #
|
||||
MAIL_ENABLED=true
|
||||
MAIL_CMD="mail"
|
||||
MAIL_RECIPIENTS=""
|
||||
MAIL_NOTIFY_ON_SUCCESS=true
|
||||
MAIL_SUBJECT_SUCCESS=" ${HOSTNAME} | Backup erfolgreich abgeschlossen"
|
||||
MAIL_SUBJECT_FAILURE=" ${HOSTNAME} | Fehler beim Backup"
|
||||
|
||||
# --- Ntfy --- #
|
||||
NTFY_ENABLED=true
|
||||
NTFY_TOPIC_URL="https://ntfy.sh/my-backup-topic"
|
||||
NTFY_AUTH_TOKEN=""
|
||||
NTFY_NOTIFY_ON_SUCCESS=true
|
||||
NTFY_TITLE_SUCCESS="Backup erfolgreich: ${HOSTNAME}"
|
||||
NTFY_TITLE_FAILURE="Backup FEHLGESCHLAGEN: ${HOSTNAME}"
|
||||
NTFY_PRIORITY_SUCCESS="3"
|
||||
NTFY_PRIORITY_FAILURE="5"
|
||||
NTFY_TAIL_LINES="200"
|
||||
|
||||
# --- Monitoring Healthcheck-Datei --- #
|
||||
# Wenn der Backup-Lauf erfolgreich war, wird diese Datei erstellt/aktualisiert.
|
||||
# Bei Fehler wird sie gelöscht.
|
||||
HEALTHCHECK_OK_FILE="/var/run/pbs-backup.ok"
|
246
v2/pbs-backup.v2.sh
Normal file
246
v2/pbs-backup.v2.sh
Normal file
@ -0,0 +1,246 @@
|
||||
#!/usr/bin/env bash
|
||||
# Script Name: pbs-backup.v2.sh
|
||||
# Beschreibung: Host-Backups zu Proxmox Backup Server (PBS) inkl. Notifications
|
||||
# Aufruf: ./pbs-backup.v2.sh [--dry-run] [--no-mail] [--no-ntfy] [-q] [-h]
|
||||
# Autor: Patrick Asmus
|
||||
# Web: https://www.cleveradmin.de
|
||||
# Git-Reposit.: https://git.techniverse.net/scriptos/pbs-backup-client-script.git
|
||||
# Version: 2.0
|
||||
# Datum: 22.08.2025
|
||||
# Modifikation: - Ntfy-Support mit Auth
|
||||
# - Logging zu Datei & Terminal (mit Timestamps)
|
||||
# - Locking, Exit-Codes, externe Config, Dry-Run, robuste Fehlerbehandlung
|
||||
# - Konfiguration ausgelagertin pbs-backup.v2.conf
|
||||
# - Backup-OK-Datei für externes Monitoring
|
||||
|
||||
set -Eeuo pipefail
|
||||
umask 077
|
||||
|
||||
# ---------- Variablen ---------- #
|
||||
SCRIPT_DIR="$(cd -- "$(dirname -- "$0")" && pwd)"
|
||||
CONFIG_FILE="${CONFIG_FILE:-$SCRIPT_DIR/pbs-backup.v2.conf}"
|
||||
|
||||
DRY_RUN=false
|
||||
FORCE_NO_MAIL=false
|
||||
FORCE_NO_NTFY=false
|
||||
VERBOSE=true
|
||||
|
||||
SCRIPT_NAME="$(basename "$0")"
|
||||
HOSTNAME="$(hostname)"
|
||||
|
||||
# ---------- Helpers ---------- #
|
||||
_timestamp() { date +"%Y-%m-%d %H:%M:%S"; }
|
||||
|
||||
log() {
|
||||
local level="$1"; shift
|
||||
local msg="$*"
|
||||
local line="[$(_timestamp)] [$level] $msg"
|
||||
echo "$line" | tee -a "$LOGFILE"
|
||||
}
|
||||
|
||||
die() {
|
||||
log "ERROR" "$*"
|
||||
exit 1
|
||||
}
|
||||
|
||||
check_dep() {
|
||||
local bin="$1" hint="${2:-}"
|
||||
command -v "$bin" >/dev/null 2>&1 || die "Benötigtes Programm '$bin' fehlt. $hint"
|
||||
}
|
||||
|
||||
bool() { [[ "${1,,}" == "true" || "$1" == "1" || "${1,,}" == "yes" ]]; }
|
||||
|
||||
print_usage() {
|
||||
cat <<EOF
|
||||
Usage: $SCRIPT_NAME [Optionen]
|
||||
|
||||
Optionen:
|
||||
--dry-run Nur anzeigen, was ausgeführt würde (kein Backup)
|
||||
--no-mail Mail-Benachrichtigung für diesen Lauf deaktivieren
|
||||
--no-ntfy Ntfy-Benachrichtigung für diesen Lauf deaktivieren
|
||||
-q, --quiet Weniger Ausgabe (nur WARN/ERROR)
|
||||
-h, --help Diese Hilfe
|
||||
|
||||
Hinweis:
|
||||
Alle variablen Einstellungen kommen aus der Config:
|
||||
$CONFIG_FILE
|
||||
Standardmäßig wird eine Datei 'pbs-backup.v2.conf' im selben Verzeichnis wie das Script erwartet.
|
||||
EOF
|
||||
}
|
||||
|
||||
# ---------- CLI ---------- #
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--dry-run) DRY_RUN=true; shift ;;
|
||||
--no-mail) FORCE_NO_MAIL=true; shift ;;
|
||||
--no-ntfy) FORCE_NO_NTFY=true; shift ;;
|
||||
-q|--quiet) VERBOSE=false; shift ;;
|
||||
-h|--help) print_usage; exit 0 ;;
|
||||
*) die "Unbekannte Option: $1 (siehe --help)" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# ---------- Config laden ---------- #
|
||||
[[ -f "$CONFIG_FILE" ]] || die "Config nicht gefunden: $CONFIG_FILE"
|
||||
source "$CONFIG_FILE"
|
||||
|
||||
[[ -n "${PBS_REPOSITORY:-}" ]] || die "PBS_REPOSITORY ist nicht gesetzt (in $CONFIG_FILE)."
|
||||
|
||||
if ! declare -p INCLUDE_DIRS >/dev/null 2>&1; then
|
||||
die "INCLUDE_DIRS ist nicht gesetzt (Array) in $CONFIG_FILE."
|
||||
fi
|
||||
[[ "${#INCLUDE_DIRS[@]}" -gt 0 ]] || die "INCLUDE_DIRS ist leer in $CONFIG_FILE."
|
||||
|
||||
[[ -n "${LOGFILE:-}" ]] || die "LOGFILE ist nicht gesetzt (in $CONFIG_FILE)."
|
||||
[[ -n "${LOCKFILE:-}" ]] || die "LOCKFILE ist nicht gesetzt (in $CONFIG_FILE)."
|
||||
|
||||
HEALTHCHECK_OK_FILE="${HEALTHCHECK_OK_FILE:-}"
|
||||
|
||||
$FORCE_NO_MAIL && MAIL_ENABLED=false
|
||||
$FORCE_NO_NTFY && NTFY_ENABLED=false
|
||||
$VERBOSE || exec >/dev/null 2>&1
|
||||
|
||||
RUNLOG="$(mktemp)"
|
||||
_cleanup() { rm -f "$RUNLOG"; }
|
||||
trap _cleanup EXIT
|
||||
|
||||
# ---------- Lock & Log ---------- #
|
||||
if ! touch "$LOGFILE" 2>/dev/null; then
|
||||
LOGFILE="/tmp/pbs-backup.v2.log"
|
||||
touch "$LOGFILE" || die "Kann Logfile nicht anlegen: $LOGFILE"
|
||||
fi
|
||||
|
||||
mkdir -p "$(dirname "$LOCKFILE")"
|
||||
exec 9>"$LOCKFILE"
|
||||
flock -n 9 || die "Es läuft bereits ein anderer Backup-Prozess (Lock: $LOCKFILE)"
|
||||
|
||||
log "INFO" "Starte $SCRIPT_NAME auf Host $HOSTNAME"
|
||||
log "INFO" "Config: $CONFIG_FILE"
|
||||
log "INFO" "Logfile: $LOGFILE"
|
||||
|
||||
check_dep "proxmox-backup-client" "Bitte PBS-Client installieren."
|
||||
if bool "${MAIL_ENABLED:-}"; then
|
||||
check_dep "${MAIL_CMD:-mail}" "Mail-/msmtp-Client nicht gefunden? Setze MAIL_CMD in $CONFIG_FILE."
|
||||
fi
|
||||
if bool "${NTFY_ENABLED:-}"; then
|
||||
check_dep "curl" "curl wird für Ntfy benötigt."
|
||||
fi
|
||||
|
||||
# ---------- Notifications ---------- #
|
||||
send_mail() {
|
||||
bool "${MAIL_ENABLED:-}" || return 0
|
||||
local subject="$1"; shift
|
||||
local body="$*"
|
||||
[[ -n "${MAIL_RECIPIENTS:-}" ]] || { log "WARN" "MAIL_RECIPIENTS leer, Mail wird übersprungen."; return 0; }
|
||||
local mail_cmd="${MAIL_CMD:-mail}"
|
||||
printf "%s\n" "$body" | $mail_cmd -s "$subject" $MAIL_RECIPIENTS || log "ERROR" "Mail-Versand fehlgeschlagen."
|
||||
}
|
||||
|
||||
send_ntfy() {
|
||||
bool "${NTFY_ENABLED:-}" || return 0
|
||||
local title="$1" priority="$2" body="$3"
|
||||
[[ -n "${NTFY_TOPIC_URL:-}" ]] || { log "WARN" "NTFY_TOPIC_URL leer, Ntfy wird übersprungen."; return 0; }
|
||||
local -a CURL_ARGS=( -sS -X POST "$NTFY_TOPIC_URL" -H "Title: $title" -H "Priority: $priority" --data-binary "$body" )
|
||||
[[ -n "${NTFY_AUTH_TOKEN:-}" ]] && CURL_ARGS+=( -H "Authorization: Bearer $NTFY_AUTH_TOKEN" )
|
||||
curl "${CURL_ARGS[@]}" >/dev/null || log "ERROR" "Ntfy-Versand fehlgeschlagen."
|
||||
}
|
||||
|
||||
# ---------- Backup ---------- #
|
||||
run_backup() {
|
||||
local cmd=("proxmox-backup-client" "backup" "--repository" "$PBS_REPOSITORY")
|
||||
|
||||
for dir in "${INCLUDE_DIRS[@]}"; do
|
||||
local base; base="$(basename "$dir")"
|
||||
cmd+=("${base}.pxar:${dir}")
|
||||
done
|
||||
|
||||
local cmd_pretty; cmd_pretty="$(printf "%q " "${cmd[@]}")"
|
||||
log "INFO" "Backup-Command: ${cmd_pretty} # PBS_PASSWORD via env"
|
||||
|
||||
if $DRY_RUN; then
|
||||
log "INFO" "DRY-RUN aktiv: Es wird nichts ausgeführt."
|
||||
return 0
|
||||
fi
|
||||
|
||||
{
|
||||
echo "===== $(_timestamp) | BEGIN BACKUP RUN ====="
|
||||
echo "Host: $HOSTNAME"
|
||||
echo "Repository: $PBS_REPOSITORY"
|
||||
echo "Quellen:"
|
||||
printf " - %s\n" "${INCLUDE_DIRS[@]}"
|
||||
echo "------------------------------------------------"
|
||||
} | tee -a "$LOGFILE" | tee -a "$RUNLOG"
|
||||
|
||||
if (
|
||||
[[ -n "${PBS_API:-}" ]] && export PBS_PASSWORD="$PBS_API"
|
||||
[[ -n "${PBS_FINGERPRINT:-}" ]] && export PBS_FINGERPRINT
|
||||
"${cmd[@]}"
|
||||
) 2>&1 | tee -a "$LOGFILE" | tee -a "$RUNLOG"
|
||||
then
|
||||
echo "===== $(_timestamp) | END BACKUP RUN (OK) =====" | tee -a "$LOGFILE" | tee -a "$RUNLOG"
|
||||
return 0
|
||||
else
|
||||
echo "===== $(_timestamp) | END BACKUP RUN (FAILED) =====" | tee -a "$LOGFILE" | tee -a "$RUNLOG"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ---------- Healthcheck ---------- #
|
||||
write_health_ok() {
|
||||
[[ -n "$HEALTHCHECK_OK_FILE" ]] || return 0
|
||||
mkdir -p "$(dirname "$HEALTHCHECK_OK_FILE")" || true
|
||||
cat > "$HEALTHCHECK_OK_FILE" <<EOF
|
||||
status=OK
|
||||
timestamp=$(date -Iseconds)
|
||||
host=$HOSTNAME
|
||||
repo=$PBS_REPOSITORY
|
||||
duration_s=$1
|
||||
EOF
|
||||
chmod 0644 "$HEALTHCHECK_OK_FILE" || true
|
||||
}
|
||||
|
||||
remove_health_ok() {
|
||||
[[ -n "$HEALTHCHECK_OK_FILE" ]] || return 0
|
||||
rm -f "$HEALTHCHECK_OK_FILE" || true
|
||||
}
|
||||
|
||||
# ---------- Main ---------- #
|
||||
START_EPOCH="$(date +%s)"
|
||||
STATUS="unknown"
|
||||
EXIT_CODE=1
|
||||
NTFY_TAIL_LINES="${NTFY_TAIL_LINES:-200}"
|
||||
|
||||
if run_backup; then
|
||||
STATUS="success"
|
||||
log "INFO" "Backup erfolgreich abgeschlossen."
|
||||
if bool "${MAIL_NOTIFY_ON_SUCCESS:-}"; then
|
||||
send_mail "${MAIL_SUBJECT_SUCCESS:-" ${HOSTNAME} | Backup erfolgreich abgeschlossen"}" \
|
||||
"$(printf "Das Backup wurde erfolgreich abgeschlossen.\n\n--- Letzte %s Zeilen ---\n%s" "$NTFY_TAIL_LINES" "$(tail -n "$NTFY_TAIL_LINES" "$RUNLOG")")"
|
||||
fi
|
||||
if bool "${NTFY_NOTIFY_ON_SUCCESS:-}"; then
|
||||
send_ntfy "${NTFY_TITLE_SUCCESS:-"Backup erfolgreich: ${HOSTNAME}"}" \
|
||||
"${NTFY_PRIORITY_SUCCESS:-3}" \
|
||||
"$(tail -n "$NTFY_TAIL_LINES" "$RUNLOG")"
|
||||
fi
|
||||
EXIT_CODE=0
|
||||
else
|
||||
STATUS="failure"
|
||||
log "ERROR" "Fehler beim Backup."
|
||||
send_mail "${MAIL_SUBJECT_FAILURE:-" ${HOSTNAME} | Fehler beim Backup"}" \
|
||||
"$(printf "Es ist ein Fehler beim Backup aufgetreten.\n\n--- Letzte %s Zeilen ---\n%s" "${NTFY_TAIL_LINES}" "$(tail -n "$NTFY_TAIL_LINES" "$RUNLOG")")"
|
||||
send_ntfy "${NTFY_TITLE_FAILURE:-"Backup FEHLGESCHLAGEN: ${HOSTNAME}"}" \
|
||||
"${NTFY_PRIORITY_FAILURE:-5}" \
|
||||
"$(tail -n "$NTFY_TAIL_LINES" "$RUNLOG")"
|
||||
EXIT_CODE=1
|
||||
fi
|
||||
|
||||
DURATION="$(( $(date +%s) - START_EPOCH ))"
|
||||
log "INFO" "Ende ($STATUS) | Dauer: ${DURATION}s"
|
||||
|
||||
if [[ "$EXIT_CODE" -eq 0 ]]; then
|
||||
write_health_ok "$DURATION"
|
||||
else
|
||||
remove_health_ok
|
||||
fi
|
||||
|
||||
exit "$EXIT_CODE"
|
Loading…
x
Reference in New Issue
Block a user