Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2fa79afd66 | |||
| 15e86400f0 | |||
| 1166a9c03e | |||
| c519aac1d9 | |||
| effc9646be | |||
| e2960c19b4 | |||
| 7d42984bfa | |||
| f0890c61ff | |||
| eab882aa44 | |||
| 87eb3307cb | |||
| 067fe8f1af | |||
| e2f64a4491 | |||
| ca8c2854a9 | |||
| 3fbb50e2bb | |||
| f7b9acd73b | |||
| 76a081468d | |||
| 75534137ff | |||
| beb53968a4 | |||
| dcae51da9f | |||
| 87c2d13069 | |||
| 602cfe21b0 | |||
| 7d3e53b42a | |||
| a15a7bad54 | |||
| 849b5e9570 | |||
| 1221a6cf23 | |||
| 0db8fee019 | |||
| 564939053a | |||
| 127431689a | |||
| f999ff6a87 | |||
| 8e121cb75c | |||
| 2329aa7377 | |||
| 7eb712fae4 | |||
| 93780dad1b | |||
| 802b7b8c63 | |||
| e6842f1de8 | |||
| 25220beae2 |
+3
-1
@@ -1,13 +1,14 @@
|
||||
# Beispielhafte Aufrufe
|
||||
|
||||
Befehl Wirkung
|
||||
```
|
||||
./miyagi-backup.sh -c /etc/miyagi.conf Führt den vollständigen Backup-Prozess aus
|
||||
./miyagi-backup.sh help Listet alle verfügbaren Funktionen
|
||||
./miyagi-backup.sh run_updates Führt nur Updates lokal aus
|
||||
./miyagi-backup.sh run_pbs_backup Führt nur das vzdump-PBS-Backup aus
|
||||
./miyagi-backup.sh run_maintenance Nur Wartung (Prune + GC)
|
||||
./miyagi-backup.sh shutdown_if_requested Prüft ob Shutdown nötig ist
|
||||
|
||||
```
|
||||
|
||||
####
|
||||
|
||||
@@ -25,3 +26,4 @@ Dieses Skript überprüft eine Bash-basierte Konfigurationsdatei für ein Backup
|
||||
## Nutzung:
|
||||
```bash
|
||||
./miyagi-check.sh /pfad/zur/config
|
||||
```
|
||||
+11
-6
@@ -2,32 +2,37 @@
|
||||
|
||||
UPDATES='yes' # Proxmox VE und PBS Updates nach dem Lauf
|
||||
SHUTDOWN='no' # System nach Ausführung herunterfahren?
|
||||
DYNROUTE='no' #Dynroute setzen?
|
||||
DDNS_GATEWAY='192.168.66.1' # Gateway
|
||||
DDNS_SERVER='1.1.1.1' # Externer DNS Server
|
||||
REBOOT='no' # Reboot nach Update?
|
||||
|
||||
# Quelle (Proxmox VE System, das gesichert wird)
|
||||
SSHPORT='22' # SSH-Port, normalerweise 22
|
||||
SOURCEPORT='22' # SSH-Port, normalerweise 22
|
||||
SOURCEHOST='192.168.50.200' # IP des Quell-Proxmox-Servers
|
||||
|
||||
# Replikation (ZFS)
|
||||
ZFSROOT='rpool/data' # Erstes Dataset vom Quellsystem
|
||||
ZFSSECOND='rpool-hdd/data' # Optional zweites Dataset
|
||||
ZFSTRGT='rpool-ssd1/repl/pve200' # Zielpfad für Replikation
|
||||
ZFSTRGT='rpool/repl/pve200' # Zielpfad für Replikation
|
||||
|
||||
# ZFS Zsync Replikation
|
||||
ZSYNC='yes' # ZSYNC aktivieren (ja/nein)
|
||||
ZPUSHTAG='bashclub:zsync-198-ssd' # Benutzer-Tag für ZFS
|
||||
ZPUSHTAG='bashclub:zsync' # Benutzer-Tag für ZFS
|
||||
ZPUSHMINKEEP='3' # Mindestens zu behaltende Snapshots
|
||||
ZPUSHKEEP='14' # Snapshots mit dem Tag, die behalten werden
|
||||
ZPUSHLABEL='zsync-rz' # Suffix für Snapshot-Autoengine
|
||||
ZPUSHLABEL='zsync' # Suffix für Snapshot-Autoengine
|
||||
ZPUSHFILTER='hourly|daily|weekly|monthly' # Weitere Filter (leer lassen oder Muster wie daily| weekly etc.)
|
||||
|
||||
# Backup mit Proxmox Backup Server
|
||||
BACKUPSERVER='no' # Backup via PBS aktivieren?
|
||||
MAINTDAY='7' # Wartungstag (1=Mo, 7=So)
|
||||
PBSHOST='192.168.50.199' # IP des Proxmox Backup Servers
|
||||
PBSPORT='22'
|
||||
BACKUPSTORE='backup' # Datastore auf Quell-Proxmox
|
||||
BACKUPSTOREPBS='backup' # Datastore auf PBS
|
||||
BACKUPEXCLUDE='10,3252,3253,3254' # VM/CT-IDs, die vom Backup ausgeschlossen sind
|
||||
REPLEXCLUDE="$BACKUPEXCLUDE" # Diese auch von Replikation ausschließen
|
||||
BACKUPEXCLUDE='9999,99988' # VM/CT-IDs, die vom Backup ausgeschlossen sind
|
||||
REPLEXCLUDE=$BACKUPEXCLUDE # Diese auch von Replikation ausschließen
|
||||
|
||||
# Zusätzliche Monitoring-Ziele
|
||||
# External Piggyback Host
|
||||
|
||||
+600
-316
File diff suppressed because it is too large
Load Diff
+43
-26
@@ -2,6 +2,7 @@
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
PERMITROOT_YES_HOSTS=()
|
||||
LOG() {
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
|
||||
}
|
||||
@@ -9,39 +10,31 @@ LOG() {
|
||||
CONFIG_FILE="${1:-}"
|
||||
|
||||
if [[ -z "$CONFIG_FILE" ]]; then
|
||||
LOG "❌ Keine Konfigurationsdatei übergeben."
|
||||
LOG "Keine Konfigurationsdatei übergeben."
|
||||
echo "Usage: $0 /pfad/zur/config"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -f "$CONFIG_FILE" ]]; then
|
||||
LOG "❌ Konfigurationsdatei nicht gefunden: $CONFIG_FILE"
|
||||
LOG "Konfigurationsdatei nicht gefunden: $CONFIG_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! bash -n "$CONFIG_FILE"; then
|
||||
LOG "❌ Syntaxfehler in der Konfigurationsdatei!"
|
||||
LOG "Syntaxfehler in der Konfigurationsdatei!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source "$CONFIG_FILE"
|
||||
|
||||
REQUIRED_VARS=(
|
||||
SSHPORT
|
||||
SOURCEPORT
|
||||
BACKUPSERVER
|
||||
ZSYNC
|
||||
MAINTDAY
|
||||
SHUTDOWN
|
||||
UPDATES
|
||||
SOURCEHOST
|
||||
ZFSROOT
|
||||
ZFSSECOND
|
||||
ZFSTRGT
|
||||
ZPUSHTAG
|
||||
ZPUSHMINKEEP
|
||||
ZPUSHKEEP
|
||||
ZPUSHLABEL
|
||||
ZPUSHFILTER
|
||||
PBSHOST
|
||||
BACKUPSTORE
|
||||
BACKUPSTOREPBS
|
||||
@@ -96,7 +89,7 @@ esac
|
||||
check_ssh_connection() {
|
||||
local host=$1
|
||||
LOG "Prüfe SSH-Verbindung zu $host ..."
|
||||
if ssh -p "$SSHPORT" -o BatchMode=yes -o ConnectTimeout=5 "$host" "echo OK" 2>/dev/null | grep -q OK; then
|
||||
if ssh -p "$SOURCEPORT" -o BatchMode=yes -o ConnectTimeout=5 "$host" "echo OK" 2>/dev/null | grep -q OK; then
|
||||
LOG " SSH-Verbindung zu $host erfolgreich."
|
||||
return 0
|
||||
else
|
||||
@@ -113,20 +106,19 @@ check_and_copy_ssh_key() {
|
||||
LOG " Lokaler SSH-Public-Key ($keyfile) nicht gefunden!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local pubkey
|
||||
pubkey=$(<"$keyfile")
|
||||
|
||||
LOG " Prüfe, ob SSH-Key auf $host autorisiert ist ..."
|
||||
|
||||
if ssh -p "$SSHPORT" "$host" "grep -qF '$pubkey' ~/.ssh/authorized_keys" 2>/dev/null; then
|
||||
if ssh -p "$SOURCEPORT" "$host" "grep -qF '$pubkey' ~/.ssh/authorized_keys" 2>/dev/null; then
|
||||
LOG " SSH-Key ist bereits auf $host hinterlegt."
|
||||
else
|
||||
LOG " SSH-Key nicht auf $host vorhanden."
|
||||
|
||||
read -rp " Möchtest du den SSH-Key jetzt via ssh-copy-id übertragen? [j/N] " ans
|
||||
if [[ "$ans" =~ ^[JjYy]$ ]]; then
|
||||
ssh-copy-id -p "$SSHPORT" "$host"
|
||||
ssh-copy-id -p "$SOURCEPORT" "$host"
|
||||
else
|
||||
LOG " SSH-Key nicht übertragen."
|
||||
fi
|
||||
@@ -138,7 +130,7 @@ check_sshd_config_recommendation() {
|
||||
LOG " Prüfe sshd_config auf $host bzgl. 'PermitRootLogin'..."
|
||||
|
||||
local current_setting
|
||||
current_setting=$(ssh -p "$SSHPORT" "$host" "grep -i '^PermitRootLogin' /etc/ssh/sshd_config" 2>/dev/null || echo "")
|
||||
current_setting=$(ssh -p "$SOURCEPORT" "$host" "grep -i '^PermitRootLogin' /etc/ssh/sshd_config" 2>/dev/null || echo "")
|
||||
|
||||
if [[ -z "$current_setting" ]]; then
|
||||
LOG " Keine explizite 'PermitRootLogin'-Einstellung gefunden."
|
||||
@@ -154,31 +146,56 @@ check_sshd_config_recommendation() {
|
||||
check_pveversion() {
|
||||
local host=$1
|
||||
LOG "Prüfe PVE-Version auf $host ..."
|
||||
if ssh -p "$SSHPORT" "$host" "command -v pveversion >/dev/null"; then
|
||||
ssh -p "$SSHPORT" "$host" "pveversion" | while read -r line; do
|
||||
if ssh -p "$SOURCEPORT" "$host" "command -v pveversion >/dev/null"; then
|
||||
ssh -p "$SOURCEPORT" "$host" "pveversion" | while read -r line; do
|
||||
LOG " $host: $line"
|
||||
done
|
||||
else
|
||||
LOG " 'pveversion' ist auf $host nicht verfügbar – kein Proxmox?"
|
||||
fi
|
||||
}
|
||||
|
||||
check_pbs_version() {
|
||||
local host=$1
|
||||
local port=$2
|
||||
LOG "Prüfe PBS-Version auf $host ..."
|
||||
if ssh -p "$port" "$host" "command -v proxmox-backup-manager >/dev/null"; then
|
||||
ssh -p "$port" "$host" "proxmox-backup-manager version" | while read -r line; do
|
||||
LOG " $host: $line"
|
||||
done
|
||||
else
|
||||
LOG " 'proxmox-backup-manager' ist auf $host nicht verfügbar – kein PBS?"
|
||||
fi
|
||||
}
|
||||
run_host_check() {
|
||||
local host=$1
|
||||
local type=${2:-pve}
|
||||
local port=$SOURCEPORT
|
||||
local pbsport=$PBSPORT
|
||||
|
||||
LOG ""
|
||||
LOG "=== Prüfung für Host: $host ==="
|
||||
if check_ssh_connection "$host"; then
|
||||
LOG "=== Prüfung für Host: $host (Typ: $type) ==="
|
||||
|
||||
if check_ssh_connection "$host" "$port"; then
|
||||
check_and_copy_ssh_key "$host"
|
||||
check_sshd_config_recommendation "$host"
|
||||
check_pveversion "$host"
|
||||
|
||||
if [[ "$type" == "pve" ]]; then
|
||||
check_pveversion "$host" "$port"
|
||||
elif [[ "$type" == "pbs" ]]; then
|
||||
check_pbs_version "$host" "$pbsport"
|
||||
else
|
||||
LOG " Unbekannter Host-Typ: $type"
|
||||
fi
|
||||
fi
|
||||
echo ""
|
||||
}
|
||||
|
||||
run_host_check "$SOURCEHOST"
|
||||
|
||||
|
||||
run_host_check "$SOURCEHOST" pve
|
||||
|
||||
if [[ "$BACKUPSERVER" == "yes" ]]; then
|
||||
run_host_check "$PBSHOST"
|
||||
run_host_check "$PBSHOST" pbs
|
||||
else
|
||||
LOG " BACKUPSERVER ist deaktiviert PBSHOST wird übersprungen."
|
||||
fi
|
||||
@@ -195,7 +212,7 @@ if [[ ${#PERMITROOT_YES_HOSTS[@]} -gt 0 ]]; then
|
||||
if [[ "$change_ans" =~ ^[JjYy]$ ]]; then
|
||||
for h in "${PERMITROOT_YES_HOSTS[@]}"; do
|
||||
echo "Ändere sshd_config auf $h ..."
|
||||
ssh -p "$SSHPORT" "$h" "sed -i 's/^PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config && systemctl reload sshd && echo '✅ sshd auf $h neu geladen.' || echo '❌ Fehler bei $h'"
|
||||
ssh -p "$SOURCEPORT" "$h" "sed -i 's/^PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config && systemctl reload sshd && echo '✅ sshd auf $h neu geladen.' || echo '❌ Fehler bei $h'"
|
||||
done
|
||||
else
|
||||
echo " Änderung von sshd_config übersprungen."
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
log() {
|
||||
echo "[INFO] $*"
|
||||
}
|
||||
|
||||
error_exit() {
|
||||
echo "[ERROR] $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
sanitize_value() {
|
||||
echo "$1" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'
|
||||
}
|
||||
|
||||
load_config() {
|
||||
local config_file="$1"
|
||||
if [[ ! -f "$config_file" ]]; then
|
||||
error_exit "Konfigurationsdatei nicht gefunden: $config_file"
|
||||
fi
|
||||
|
||||
log "Lade und bereinige Konfigurationsdatei: $config_file"
|
||||
while IFS='=' read -r key value; do
|
||||
# nur gültige Variablennamen parsen
|
||||
if [[ "$key" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]]; then
|
||||
# Kommentar nach Wert entfernen
|
||||
value="${value%%#*}"
|
||||
value="$(sanitize_value "$value")"
|
||||
# Variable setzen (für den write_new_config Zugriff)
|
||||
eval "$key=\"$value\""
|
||||
fi
|
||||
done < "$config_file"
|
||||
}
|
||||
|
||||
write_new_config() {
|
||||
local out_file="$1"
|
||||
|
||||
cat > "$out_file" <<EOF
|
||||
#Edit all Variables for best Experience
|
||||
|
||||
UPDATES='${UPDATES}' # Proxmox VE und PBS Updates nach dem Lauf
|
||||
SHUTDOWN='${SHUTDOWN}' # System nach Ausführung herunterfahren?
|
||||
|
||||
# Quelle (Proxmox VE System, das gesichert wird)
|
||||
SOURCEPORT='${SOURCEPORT}' # SSH-Port, normalerweise 22
|
||||
SOURCEHOST='${SOURCEHOST}' # IP des Quell-Proxmox-Servers
|
||||
|
||||
# Replikation (ZFS)
|
||||
ZFSROOT='${ZFSROOT}' # Erstes Dataset vom Quellsystem
|
||||
ZFSSECOND='${ZFSSECOND}' # Optional zweites Dataset
|
||||
ZFSTRGT='${ZFSTRGT}' # Zielpfad für Replikation
|
||||
|
||||
# ZFS Zsync Replikation
|
||||
ZSYNC='${ZSYNC}' # ZSYNC aktivieren (ja/nein)
|
||||
ZPUSHTAG='${ZPUSHTAG}' # Benutzer-Tag für ZFS
|
||||
ZPUSHMINKEEP='${ZPUSHMINKEEP}' # Mindestens zu behaltende Snapshots
|
||||
ZPUSHKEEP='${ZPUSHKEEP}' # Snapshots mit dem Tag, die behalten werden
|
||||
ZPUSHLABEL='${ZPUSHLABEL}' # Suffix für Snapshot-Autoengine
|
||||
ZPUSHFILTER='${ZPUSHFILTER}' # Weitere Filter (leer lassen oder Muster wie daily| weekly etc.)
|
||||
|
||||
# Backup mit Proxmox Backup Server
|
||||
BACKUPSERVER='${BACKUPSERVER}' # Backup via PBS aktivieren?
|
||||
MAINTDAY='${MAINTDAY}' # Wartungstag (1=Mo, 7=So)
|
||||
PBSHOST='${PBSHOST}' # IP des Proxmox Backup Servers
|
||||
BACKUPSTORE='${BACKUPSTORE}' # Datastore auf Quell-Proxmox
|
||||
BACKUPSTOREPBS='${BACKUPSTOREPBS}' # Datastore auf PBS
|
||||
BACKUPEXCLUDE='${BACKUPEXCLUDE}' # VM/CT-IDs, die vom Backup ausgeschlossen sind
|
||||
REPLEXCLUDE=\$BACKUPEXCLUDE # Diese auch von Replikation ausschließen
|
||||
|
||||
# Zusätzliche Monitoring-Ziele
|
||||
# External Piggyback Host
|
||||
EPIGGYBACK='${EPIGGYBACK}' # Piggyback-Daten an Monitoring-Ziel senden?
|
||||
EPIGGYBACK_PORT='${EPIGGYBACK_PORT}' # SSH-Port für EPIGGYBACK_HOST
|
||||
EPIGGYBACK_HOST='${EPIGGYBACK_HOST}' # Monitoring-Zielhost für Piggyback
|
||||
|
||||
# External Checkzfs Host
|
||||
ECHECKZFS='${ECHECKZFS}' # check_zfs-Output an Monitoring-Ziel senden?
|
||||
ECHECKZFS_PORT='${ECHECKZFS_PORT}' # SSH-Port für ECHECKZFS_HOST
|
||||
ECHECKZFS_HOST='${ECHECKZFS_HOST}' # Monitoring-Zielhost für check_zfs
|
||||
EOF
|
||||
}
|
||||
|
||||
|
||||
if [[ $# -ne 1 ]]; then
|
||||
echo "Usage: $0 <configfile>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ORIGINAL="$1"
|
||||
|
||||
read -rp "Soll die aktuelle Datei als Backup gesichert werden (umbenennen)? (ja/nein): " RESPONSE
|
||||
RESPONSE="${RESPONSE,,}"
|
||||
|
||||
if [[ "$RESPONSE" == "ja" || "$RESPONSE" == "j" ]]; then
|
||||
BACKUPFILE="${ORIGINAL}.bak"
|
||||
mv "$ORIGINAL" "$BACKUPFILE"
|
||||
log "Originaldatei wurde umbenannt in: $BACKUPFILE"
|
||||
CONFIG_TO_READ="$BACKUPFILE"
|
||||
else
|
||||
log "Keine Sicherung der Originaldatei durchgeführt. Original bleibt unverändert."
|
||||
CONFIG_TO_READ="$ORIGINAL"
|
||||
fi
|
||||
|
||||
NEWFILE="${ORIGINAL}.convert"
|
||||
load_config "$CONFIG_TO_READ"
|
||||
write_new_config "$NEWFILE"
|
||||
log "Neue Konfiguration geschrieben in: $NEWFILE"
|
||||
@@ -0,0 +1,255 @@
|
||||
#!/bin/bash
|
||||
# Author: (C) 2025 Patrick Perlbach <patrick@perlbach24.de>
|
||||
# --- Konfiguration und Initiale Variablen ---
|
||||
FORCE_YES=0
|
||||
DRY_RUN=0
|
||||
CONFIG_FILE=""
|
||||
|
||||
# --- Hilfsfunktionen ---
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $0 -c <config> [--yes] [--dry-run]
|
||||
|
||||
-c <file> Pfad zur Konfigurationsdatei (Pflicht)
|
||||
--yes Automatische Ausführung ohne Rückfrage
|
||||
--dry-run Zeigt nur, was gemacht würde
|
||||
--help Diese Hilfe anzeigen
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
run_or_echo() {
|
||||
if [[ "$DRY_RUN" == "1" ]]; then
|
||||
echo "[DRY-RUN] $*"
|
||||
else
|
||||
eval "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
parse_args() {
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-c) CONFIG_FILE="$2"; shift 2 ;;
|
||||
--yes) FORCE_YES=1; shift ;;
|
||||
--dry-run) DRY_RUN=1; shift ;;
|
||||
--help) usage ;;
|
||||
*) echo "[ERROR] Unbekannter Parameter: $1"; usage ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -z "$CONFIG_FILE" || ! -f "$CONFIG_FILE" ]] && {
|
||||
echo "[ERROR] Konfigurationsdatei fehlt oder ungültig!"
|
||||
exit 1
|
||||
}
|
||||
|
||||
source "$CONFIG_FILE"
|
||||
}
|
||||
|
||||
confirm() {
|
||||
if [[ "$FORCE_YES" -eq 1 ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
while true; do
|
||||
read -rp "$1 [j/N]: " yn
|
||||
case $yn in
|
||||
[JjYy]*) return 0 ;;
|
||||
[Nn]*|"") return 1 ;;
|
||||
*) echo "Bitte j (ja) oder n (nein) eingeben." ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
install_cmk() {
|
||||
echo "[INFO] Lade cmk.deb herunter..."
|
||||
run_or_echo "curl -fsSL \"$CMK_URL\" -o \"$CMK_FILE\""
|
||||
|
||||
echo "[INFO] Installiere cmk.deb..."
|
||||
run_or_echo "sudo apt install -y \"$CMK_FILE\""
|
||||
}
|
||||
|
||||
install_fix_interface_names() {
|
||||
echo "[INFO] Installiere Fix für Interface-Namen..."
|
||||
run_or_echo "wget -O /tmp/debian-fix-interface-names.sh \"$FIX_INTERFACE_NAMES_URL\""
|
||||
run_or_echo "chmod +x /tmp/debian-fix-interface-names.sh"
|
||||
run_or_echo "bash /tmp/debian-fix-interface-names.sh"
|
||||
}
|
||||
|
||||
install_miyagi_scripts() {
|
||||
echo "[INFO] Lade Miyagi-Backup-Skripte..."
|
||||
run_or_echo "wget -O miyagi-backup.sh \"$MIYAGI_BACKUP_URL\""
|
||||
run_or_echo "wget -O miyagi-check.sh \"$MIYAGI_CHECK_URL\""
|
||||
run_or_echo "wget -O miyagi-convert.sh \"$MIYAGI_CONVERT_URL\""
|
||||
run_or_echo "mkdir -p /root/miyagi-backup"
|
||||
run_or_echo "mv miyagi-backup.sh miyagi-check.sh miyagi-convert.sh /root/miyagi-backup/"
|
||||
run_or_echo "chmod +x /root/miyagi-backup/*.sh"
|
||||
}
|
||||
|
||||
install_checkmk_plugins() {
|
||||
echo "[INFO] Installiere disk_smart_info Plugin..."
|
||||
run_or_echo "curl -fsSL \"$DISK_SMART_INFO_URL\" -o /usr/lib/check_mk_agent/plugins/disk_smart_info"
|
||||
run_or_echo "chmod +x /usr/lib/check_mk_agent/plugins/disk_smart_info"
|
||||
}
|
||||
|
||||
install_cleansnaps() {
|
||||
echo "[INFO] Installiere cleansnaps Skript..."
|
||||
run_or_echo "wget -O /usr/local/bin/cleansnaps \"$CLEANSNAPS_URL\""
|
||||
run_or_echo "chmod +x /usr/local/bin/cleansnaps"
|
||||
}
|
||||
|
||||
install_check_snapshot_age() {
|
||||
echo "[INFO] Installiere check-snapshot-age..."
|
||||
run_or_echo "wget -O /usr/local/bin/check-snapshot-age \"$CHECK_SNAPSHOT_AGE_URL\""
|
||||
run_or_echo "chmod +x /usr/local/bin/check-snapshot-age"
|
||||
}
|
||||
|
||||
install_checkzfs() {
|
||||
echo "[INFO] Installiere checkzfs..."
|
||||
run_or_echo "wget -O /usr/local/bin/checkzfs \"$CHECKZFS_URL\""
|
||||
run_or_echo "chmod +x /usr/local/bin/checkzfs"
|
||||
}
|
||||
|
||||
check_ssh() {
|
||||
echo "[INFO] Teste SSH-Verbindung zu $SOURCEHOST ..."
|
||||
|
||||
if ssh -p "$SOURCEPORT" -o BatchMode=yes -o ConnectTimeout=5 root@"$SOURCEHOST" "echo Verbindung erfolgreich" 2>/dev/null; then
|
||||
echo "[OK] SSH-Verbindung über Schlüssel funktioniert."
|
||||
else
|
||||
echo "[WARN] Keine Schlüsselbasierte SSH-Verbindung möglich oder abgelehnt."
|
||||
|
||||
echo "[HINWEIS] Eine Passwortabfrage erfolgt jetzt – dies ist normal."
|
||||
if ssh -p "$SOURCEPORT" root@"$SOURCEHOST" "echo Verbindung erfolgreich"; then
|
||||
echo "[OK] SSH-Verbindung per Passwort erfolgreich."
|
||||
|
||||
if confirm "Möchtest du den lokalen SSH-Schlüssel auf $SOURCEHOST kopieren (per ssh-copy-id)?"; then
|
||||
run_or_echo "ssh-copy-id -p \"$SOURCEPORT\" root@\"$SOURCEHOST\""
|
||||
echo "[INFO] Bitte erneut starten, um die Schlüsselverbindung zu nutzen."
|
||||
exit 0
|
||||
else
|
||||
echo "[HINWEIS] Es wird weiterhin Passwortabfrage benötigt."
|
||||
fi
|
||||
else
|
||||
echo "[FEHLER] SSH-Verbindung nicht möglich – bitte Zugang prüfen!"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
select_zfs_pools() {
|
||||
echo "[INFO] Lade ZFS-Datasets vom Remote-Host..."
|
||||
|
||||
LOCAL_HOSTNAME=$(hostname -s)
|
||||
REMOTE_HOSTNAME=$(ssh -p "$SOURCEPORT" root@"$SOURCEHOST" "hostname -s")
|
||||
TAG_KEY="bashclub:miyagi-${REMOTE_HOSTNAME}-${LOCAL_HOSTNAME}"
|
||||
TAG_VALUE="subvols"
|
||||
|
||||
# Hole alle relevanten Pool-Namen
|
||||
mapfile -t pools < <(ssh -p "$SOURCEPORT" root@"$SOURCEHOST" \
|
||||
"zfs list -H -o name" | \
|
||||
grep -E '/(vm|subvol)-' | \
|
||||
grep -viE 'repl|replica' | \
|
||||
sed 's:/[^/]*$::' | \
|
||||
sort -u)
|
||||
|
||||
if [[ ${#pools[@]} -eq 0 ]]; then
|
||||
echo "[WARN] Keine geeigneten Datasets gefunden!"
|
||||
return
|
||||
fi
|
||||
|
||||
local options=()
|
||||
local tagged_pools=()
|
||||
|
||||
for pool in "${pools[@]}"; do
|
||||
local tag status
|
||||
tag=$(ssh -p "$SOURCEPORT" root@"$SOURCEHOST" zfs get -H -o value "$TAG_KEY" "$pool" 2>/dev/null)
|
||||
if [[ "$tag" == "$TAG_VALUE" ]]; then
|
||||
status="on"
|
||||
tagged_pools+=("$pool")
|
||||
else
|
||||
status="off"
|
||||
fi
|
||||
options+=("$pool" "$([[ "$status" == "on" ]] && echo 'TAGGED' || echo 'untagged')" "$status")
|
||||
done
|
||||
|
||||
local selected
|
||||
selected=$(whiptail --title "ZFS Pools auswählen" \
|
||||
--checklist "Wähle Datasets zum Taggen aus:" 20 78 12 \
|
||||
"${options[@]}" \
|
||||
3>&1 1>&2 2>&3)
|
||||
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "[INFO] Auswahl abgebrochen."
|
||||
return
|
||||
fi
|
||||
|
||||
local selected_array=()
|
||||
eval "selected_array=($selected)"
|
||||
|
||||
echo "[INFO] Verarbeite Tagging für ausgewählte Pools:"
|
||||
|
||||
for ((i = 0; i < ${#options[@]}; i += 3)); do
|
||||
local pool="${options[i]}"
|
||||
local prev_status="${options[i+2]}"
|
||||
local is_selected=0
|
||||
|
||||
for sel in "${selected_array[@]}"; do
|
||||
if [[ "$sel" == "$pool" ]]; then
|
||||
is_selected=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "$is_selected" -eq 1 && "$prev_status" == "off" ]]; then
|
||||
echo " → Tagge $pool"
|
||||
run_or_echo ssh -p "$SOURCEPORT" root@"$SOURCEHOST" zfs set "$TAG_KEY=$TAG_VALUE" "$pool"
|
||||
elif [[ "$is_selected" -eq 0 && "$prev_status" == "on" ]]; then
|
||||
echo " → Entferne Tag von $pool"
|
||||
run_or_echo ssh -p "$SOURCEPORT" root@"$SOURCEHOST" zfs inherit "$TAG_KEY" "$pool"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
main() {
|
||||
# URLs und Dateipfade als Variablen, ggf. in Kopfbereich auslagern
|
||||
CMK_URL="https://nc.sysops.de/index.php/s/YofRT5LBfX5ZDQs/download/cmk.deb"
|
||||
CMK_FILE="/tmp/cmk.deb"
|
||||
|
||||
FIX_INTERFACE_NAMES_URL="https://raw.githubusercontent.com/bashclub/trmm-scripts/refs/heads/main/debian-fix-interface-names.sh"
|
||||
|
||||
MIYAGI_BACKUP_URL="https://gitea.perlbach24.de/scripte/miyagi-backup/raw/branch/main/miyagi-backup.sh"
|
||||
MIYAGI_CHECK_URL="https://gitea.perlbach24.de/scripte/miyagi-backup/raw/branch/main/miyagi-check.sh"
|
||||
MIYAGI_CONVERT_URL="https://gitea.perlbach24.de/scripte/miyagi-backup/raw/branch/main/miyagi-convert.sh"
|
||||
|
||||
DISK_SMART_INFO_URL="https://raw.githubusercontent.com/bashclub/checkmk-smart/main/disk_smart_info.py"
|
||||
|
||||
CLEANSNAPS_URL="https://raw.githubusercontent.com/bashclub/zfs-housekeeping/refs/heads/main/cleansnaps.sh"
|
||||
|
||||
CHECK_SNAPSHOT_AGE_URL="https://gitea.perlbach24.de/scripte/check-zfs-replication/raw/branch/main/check-snapshot-age"
|
||||
|
||||
CHECKZFS_URL="https://gitea.perlbach24.de/scripte/check-zfs-replication/raw/branch/main/checkzfs.py"
|
||||
|
||||
echo "[INFO] Starte Installation mit Konfig: $CONFIG_FILE"
|
||||
|
||||
install_cmk
|
||||
|
||||
install_fix_interface_names
|
||||
|
||||
install_miyagi_scripts
|
||||
|
||||
install_checkmk_plugins
|
||||
|
||||
install_cleansnaps
|
||||
|
||||
install_check_snapshot_age
|
||||
|
||||
install_checkzfs
|
||||
check_ssh
|
||||
select_zfs_pools
|
||||
|
||||
echo "[OK] Installation abgeschlossen."
|
||||
}
|
||||
|
||||
# Start
|
||||
parse_args "$@"
|
||||
main
|
||||
Reference in New Issue
Block a user