Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2954647d87 | |||
| 0efa02e0c2 | |||
| cdf6d522cb | |||
| b0fdaedfaf | |||
| db358d77a3 | |||
| 65ff6cf9e2 | |||
| 0055ac78a4 | |||
| fdec6e6d9d | |||
| 76ad3cfc82 | |||
| 59d2e72e62 | |||
| e62f6f9c2d | |||
| 97eced5d12 | |||
| 01d78f433a | |||
| 133312ac4b | |||
| 56bee24fbb | |||
| b6b995f670 | |||
| 8acfffe8d2 | |||
| c707cbd8df | |||
| 4e023cd4ef | |||
| dbcb105ee8 | |||
| 3714b62b2c | |||
| 2994dbffcf | |||
| cfbc115bc9 | |||
| 9fa0cfbf71 | |||
| 3f9b7c5e64 | |||
| 15b3b5b684 | |||
| a318cea773 |
@@ -1,9 +1,27 @@
|
||||
🧪 Beispielhafte Aufrufe
|
||||
# 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
|
||||
./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
|
||||
|
||||
|
||||
####
|
||||
|
||||
# miyagi-check.sh
|
||||
|
||||
Dieses Skript überprüft eine Bash-basierte Konfigurationsdatei für ein Backup-System:
|
||||
|
||||
## Funktionen:
|
||||
- Validiert alle benötigten Variablen
|
||||
- Testet SSH-Verbindungen zu `SOURCEHOST` und optional `PBSHOST`
|
||||
- Prüft und installiert bei Bedarf den lokalen SSH-Key (`~/.ssh/id_rsa.pub`)
|
||||
- Erkennt unsichere `PermitRootLogin yes` Einstellungen
|
||||
- Bietet automatische Umstellung auf `prohibit-password` an
|
||||
|
||||
## Nutzung:
|
||||
```bash
|
||||
./miyagi-check.sh /pfad/zur/config
|
||||
+34
-27
@@ -1,34 +1,41 @@
|
||||
#Edit all Variables for best Experience
|
||||
|
||||
SSHPORT='22' #SSH Port, usually default 22 internally
|
||||
BACKUPSERVER=no #use yes for triggering Proxmox Backup to Store
|
||||
ZSYNC=yes #skip Replication with no
|
||||
MAINTDAY=7 #1 Monday to 7 Sunday, dont start your System too late
|
||||
SHUTDOWN=no #No be there anymore
|
||||
UPDATES=yes #Do PVE and PBS Updates after run
|
||||
UPDATES='yes' # Proxmox VE und PBS Updates nach dem Lauf
|
||||
SHUTDOWN='no' # System nach Ausführung herunterfahren?
|
||||
|
||||
SOURCEHOST='192.168.50.200' # IP from Proxmox VE System to be backuped and replicated daily
|
||||
# Quelle (Proxmox VE System, das gesichert wird)
|
||||
SSHPORT='22' # SSH-Port, normalerweise 22
|
||||
SOURCEHOST='192.168.50.200' # IP des Quell-Proxmox-Servers
|
||||
|
||||
#Replication
|
||||
ZFSROOT='rpool/data' #First Dataset/Datastoresourcepath from Proxmox VE System to be backuped and replicated daily
|
||||
ZFSSECOND='rpool-hdd/data' #Optional second Dataset
|
||||
ZFSTRGT='rpool-ssd1/repl/pve200' #This pulling Machines Target ZFS Sourcepath
|
||||
# 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
|
||||
|
||||
#Prevent Scrubs on Backups and Replications
|
||||
ZPOOLSRC=rpool #First Pool/Tank from Proxmox VE System to be backuped and replicated daily
|
||||
ZPOOLDST=rpool #This pulling Machines Pool/Tank
|
||||
# ZFS Zsync Replikation
|
||||
ZSYNC='yes' # ZSYNC aktivieren (ja/nein)
|
||||
ZPUSHTAG='bashclub:zsync-198-ssd' # 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
|
||||
ZPUSHFILTER='hourly|daily|weekly|monthly' # Weitere Filter (leer lassen oder Muster wie daily| weekly etc.)
|
||||
|
||||
#ZSYNC
|
||||
ZSYNC=yes #set to no for Backup with PBS only
|
||||
ZPUSHTAG=bashclub:zsync-198-ssd #ZFS User parameter will be set on ZFSROOT and ZFSSECOND to select.
|
||||
ZPUSHMINKEEP=3 #Keep min x Snapshots on all Source Datasets to resume Replication
|
||||
ZPUSHKEEP=14 #Number of Snapshots with ZPUSHLABEL
|
||||
ZPUSHLABEL=zsync-rz #Suffix for ZFS-Auto-Snapshot Engine
|
||||
ZPUSHFILTER="" #ZPUSHLABEL will be replicated. So you can add more Patterns from ZFS, line hourly, daily, weekly, monthly.
|
||||
# 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
|
||||
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
|
||||
|
||||
#Backup
|
||||
PBSHOST='192.168.50.199' #IP from your Proxmox Backupserver - dont forget to add your hosts public key to PBS authorized keys
|
||||
BACKUPSTORE=backup #Datastorename configured in your Proxmox VE System to be backuped and replicated daily
|
||||
BACKUPSTOREPBS=backup #Datastorename configured in your Proxmox Backup Server
|
||||
BACKUPEXCLUDE='124,3021,3022,3023,3251,3252,3253,3254' #Machines to be excluded from Proxmox Backup
|
||||
REPLEXCLUDE=$BACKUPEXCLUDE
|
||||
# Zusätzliche Monitoring-Ziele
|
||||
# External Piggyback Host
|
||||
EPIGGYBACK='no' # Piggyback-Daten an Monitoring-Ziel senden?
|
||||
EPIGGYBACK_PORT='222' # SSH-Port für EPIGGYBACK_HOST
|
||||
EPIGGYBACK_HOST='192.168.66.10' # Monitoring-Zielhost für Piggyback
|
||||
|
||||
# External Checkzfs Host
|
||||
ECHECKZFS='no' # check_zfs-Output an Monitoring-Ziel senden?
|
||||
ECHECKZFS_PORT='2222' # SSH-Port für ECHECKZFS_HOST
|
||||
ECHECKZFS_HOST='192.168.50.210' # Monitoring-Zielhost für check_zfs
|
||||
+284
-30
@@ -1,5 +1,5 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
set -uo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin"
|
||||
@@ -18,7 +18,6 @@ usage() {
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Konfigurationsdatei initialisieren (nur wenn -c übergeben)
|
||||
CONFIG_FILE=""
|
||||
while getopts "c:" opt; do
|
||||
case "$opt" in
|
||||
@@ -28,15 +27,117 @@ while getopts "c:" opt; do
|
||||
done
|
||||
|
||||
# Bei Einzelaufruf muss Konfiguration geladen sein
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
if [[ -n "${CONFIG_FILE:-}" ]]; then
|
||||
if [[ ! -f "$CONFIG_FILE" ]]; then
|
||||
log "ERROR: Configuration file not found: $CONFIG_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! bash -n "$CONFIG_FILE"; then
|
||||
log "Syntaxfehler in Konfigurationsdatei $CONFIG_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source "$CONFIG_FILE"
|
||||
|
||||
# ==========================
|
||||
# Konfigurationsprüfung
|
||||
# ==========================
|
||||
REQUIRED_VARS=(
|
||||
SSHPORT
|
||||
BACKUPSERVER
|
||||
ZSYNC
|
||||
MAINTDAY
|
||||
SHUTDOWN
|
||||
UPDATES
|
||||
SOURCEHOST
|
||||
ZFSROOT
|
||||
ZFSSECOND
|
||||
ZFSTRGT
|
||||
ZPUSHTAG
|
||||
ZPUSHMINKEEP
|
||||
ZPUSHKEEP
|
||||
ZPUSHLABEL
|
||||
PBSHOST
|
||||
BACKUPSTORE
|
||||
BACKUPSTOREPBS
|
||||
BACKUPEXCLUDE
|
||||
REPLEXCLUDE
|
||||
)
|
||||
|
||||
MISSING_VARS=()
|
||||
for var in "${REQUIRED_VARS[@]}"; do
|
||||
#if [[ -z "${!var:-}" ]]; then
|
||||
if ! declare -p "$var" &>/dev/null || [[ -z "${!var}" ]]; then
|
||||
MISSING_VARS+=("$var")
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "${#MISSING_VARS[@]}" -ne 0 ]]; then
|
||||
log "Fehlende Konfigurationsvariablen:"
|
||||
for var in "${MISSING_VARS[@]}"; do
|
||||
log " - $var"
|
||||
done
|
||||
log "Breche ab – bitte Konfigurationsdatei prüfen."
|
||||
exit 1
|
||||
else
|
||||
log "Alle erforderlichen Konfigurationsvariablen sind gesetzt."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Funktionen
|
||||
remote_ssh() {
|
||||
ssh -p "$SSHPORT" "$@"
|
||||
}
|
||||
|
||||
remote_scp() {
|
||||
scp -P "$SSHPORT" "$@"
|
||||
}
|
||||
|
||||
set_wol_g_enabled() {
|
||||
log "Pruefe, ob ethtool installiert ist..."
|
||||
|
||||
if ! command -v ethtool >/dev/null 2>&1; then
|
||||
log "ethtool ist nicht installiert, versuche Installation..."
|
||||
apt update && apt install -y ethtool || {
|
||||
log "Fehler: ethtool konnte nicht installiert werden."
|
||||
return 1
|
||||
}
|
||||
else
|
||||
log "ethtool ist bereits installiert."
|
||||
fi
|
||||
|
||||
log "Pruefe und setze Wake-on-LAN (WOL) auf 'g' nur bei Interfaces mit statischer IP..."
|
||||
|
||||
for iface in $(ls /sys/class/net | grep -vE '^(lo|tap|vmbr|veth|br|docker|bond|wl)'); do
|
||||
if [[ -e "/sys/class/net/$iface/device" ]]; then
|
||||
log "Bearbeite physisches Interface: $iface"
|
||||
|
||||
# Aktuellen WOL-Status pruefen
|
||||
current_wol=$(ethtool "$iface" 2>/dev/null | awk '/Wake-on:/ {print $2}')
|
||||
if [[ "$current_wol" != "g" ]]; then
|
||||
log "Setze WOL auf 'g' fuer $iface..."
|
||||
ethtool -s "$iface" wol g || log "Fehler beim Setzen von WOL auf $iface"
|
||||
else
|
||||
log "WOL ist bereits korrekt auf 'g' fuer $iface"
|
||||
fi
|
||||
|
||||
# Pruefen, ob ein 'iface $iface inet static' Eintrag existiert
|
||||
if grep -qE "^\s*iface\s+$iface\s+inet\s+static" /etc/network/interfaces; then
|
||||
if ! grep -A 5 -E "^\s*iface\s+$iface\s+inet\s+static" /etc/network/interfaces | grep -q "post-up ethtool -s $iface wol g"; then
|
||||
log "Ergaenze WOL-Befehl im statischen Block fuer $iface..."
|
||||
sed -i "/^\s*iface\s\+$iface\s\+inet\s\+static/a \ post-up ethtool -s $iface wol g" /etc/network/interfaces
|
||||
else
|
||||
log "WOL-Befehl fuer $iface ist bereits im statischen Block vorhanden."
|
||||
fi
|
||||
else
|
||||
log "Kein statischer Eintrag fuer $iface gefunden, keine Aenderung vorgenommen."
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
write_zsync_config() {
|
||||
local conf_file="/etc/bashclub/$SOURCEHOST.conf"
|
||||
@@ -46,7 +147,7 @@ write_zsync_config() {
|
||||
echo "source=root@$SOURCEHOST"
|
||||
echo "sshport=$SSHPORT"
|
||||
echo "tag=$ZPUSHTAG"
|
||||
echo "snapshot_filter=$ZPUSHFILTER"
|
||||
echo "snapshot_filter=\"$ZPUSHFILTER\""
|
||||
echo "min_keep=$ZPUSHMINKEEP"
|
||||
echo "zfs_auto_snapshot_keep=$ZPUSHKEEP"
|
||||
echo "zfs_auto_snapshot_label=$ZPUSHLABEL"
|
||||
@@ -69,10 +170,12 @@ run_zsync() {
|
||||
fi
|
||||
}
|
||||
|
||||
run_updates() {
|
||||
log "Running updates..."
|
||||
apt update && apt dist-upgrade -y
|
||||
apt autopurge -y
|
||||
run_remote_updates() {
|
||||
if [[ "$UPDATES" == "yes" ]]; then
|
||||
ssh "$PBSHOST" apt update && apt dist-upgrade -y
|
||||
else
|
||||
log "Remote updates disabled"
|
||||
fi
|
||||
}
|
||||
|
||||
run_remote_updates() {
|
||||
@@ -84,31 +187,95 @@ run_remote_updates() {
|
||||
}
|
||||
|
||||
send_piggyback_data() {
|
||||
local fname="90000_miyagi-$SOURCEHOSTNAME-$(hostname)"
|
||||
log "Sending piggyback data to $SOURCEHOST..."
|
||||
echo "<<<<miyagi-$SOURCEHOSTNAME-$(hostname)>>>" > "$fname"
|
||||
/usr/bin/check_mk_agent >> "$fname"
|
||||
echo "<<<<>>>>" >> "$fname"
|
||||
scp "$fname" "$SOURCEHOST:/var/lib/check_mk_agent/spool/"
|
||||
# Falls SOURCEHOSTNAME leer ist, ueber SSH vom Zielhost ermitteln
|
||||
if [[ -z "${SOURCEHOSTNAME:-}" ]]; then
|
||||
log "SOURCEHOSTNAME is empty retrieving via SSH from $SOURCEHOST..."
|
||||
SOURCEHOSTNAME=$(ssh -p "$SSHPORT" "$SOURCEHOST" hostname)
|
||||
log "Detected SOURCEHOSTNAME: $SOURCEHOSTNAME"
|
||||
fi
|
||||
|
||||
local combined_host="miyagi-${SOURCEHOSTNAME}-$(hostname)"
|
||||
local filename="90000_${combined_host}"
|
||||
|
||||
log "Do nott forget to add a Host in CMK named: ${combined_host} (without Agent, Piggyback enabled)!"
|
||||
log "Creating piggyback file: $filename"
|
||||
|
||||
{
|
||||
echo "<<<<${combined_host}>>>>"
|
||||
/usr/bin/check_mk_agent
|
||||
echo "<<<<>>>>"
|
||||
} > "$filename"
|
||||
|
||||
if scp -P "$SSHPORT" "$filename" "$SOURCEHOST:/var/lib/check_mk_agent/spool/"; then
|
||||
log "Piggyback data successfully sent to $SOURCEHOST"
|
||||
else
|
||||
log "ERROR: Failed to send piggyback data to $SOURCEHOST"
|
||||
fi
|
||||
}
|
||||
|
||||
run_pbs_backup() {
|
||||
if [[ -z "${SOURCEHOSTNAME:-}" ]]; then
|
||||
SOURCEHOSTNAME=$(ssh "$SOURCEHOST" hostname)
|
||||
fi
|
||||
|
||||
log "Running PBS vzdump job..."
|
||||
ssh root@"$SOURCEHOST" vzdump --pbs-change-detection-mode metadata \
|
||||
|
||||
# PBS-Storage ggf. aktivieren
|
||||
log "Checking if PBS storage '$BACKUPSTORE' is enabled on $SOURCEHOST..."
|
||||
if ssh root@"$SOURCEHOST" "pvesm status | grep -w '$BACKUPSTORE' | grep -q 'disabled'"; then
|
||||
log "PBS storage '$BACKUPSTORE' is disabled. Attempting to enable...sleep 10 Sekunden"
|
||||
ssh root@"$SOURCEHOST" "pvesm set '$BACKUPSTORE' --disable 0 && sleep 10"
|
||||
pbs_enabled_by_script=true
|
||||
else
|
||||
log "PBS storage '$BACKUPSTORE' is already enabled."
|
||||
pbs_enabled_by_script=false
|
||||
fi
|
||||
|
||||
vzdump_success=false
|
||||
|
||||
# Hauptversuch mit --pbs-change-detection-mode
|
||||
if ssh root@"$SOURCEHOST" vzdump --pbs-change-detection-mode metadata \
|
||||
--node "$SOURCEHOSTNAME" --storage "$BACKUPSTORE" \
|
||||
--exclude "$BACKUPEXCLUDE" --mode snapshot --all 1 \
|
||||
--notes-template '{{guestname}}'
|
||||
--notes-template '{{guestname}}'; then
|
||||
|
||||
if [[ $? -eq 0 ]]; then
|
||||
log "vzdump with change-detection-mode succeeded"
|
||||
vzdump_success=true
|
||||
|
||||
else
|
||||
log "Fallback: vzdump with change-detection-mode failed, trying without it..."
|
||||
|
||||
if ssh root@"$SOURCEHOST" vzdump \
|
||||
--node "$SOURCEHOSTNAME" --storage "$BACKUPSTORE" \
|
||||
--exclude "$BACKUPEXCLUDE" --mode snapshot --all 1 \
|
||||
--notes-template '{{guestname}}'; then
|
||||
|
||||
log "Fallback vzdump succeeded"
|
||||
vzdump_success=true
|
||||
|
||||
else
|
||||
log "ERROR: vzdump failed even after fallback"
|
||||
fi
|
||||
fi
|
||||
|
||||
# PBS-Storage wieder deaktivieren, wenn zuvor aktiviert und erfolgreich
|
||||
if [[ "$vzdump_success" == true && "$pbs_enabled_by_script" == true ]]; then
|
||||
log "Disabling PBS storage '$BACKUPSTORE' again on $SOURCEHOST..."
|
||||
ssh root@"$SOURCEHOST" "pvesm set '$BACKUPSTORE' --disable 1"
|
||||
fi
|
||||
|
||||
# Monitoring-Output für Checkmk
|
||||
if [[ "$vzdump_success" == true ]]; then
|
||||
echo "0 DailyPBS - Daily Backup" > /tmp/cmk_tmp.out
|
||||
else
|
||||
echo "2 DailyPBS - Daily Backup FAILED" > /tmp/cmk_tmp.out
|
||||
fi
|
||||
|
||||
( echo "<<<local>>>" ; cat /tmp/cmk_tmp.out ) > /tmp/90000_checkpbs
|
||||
scp /tmp/90000_checkpbs root@"$SOURCEHOST":/var/lib/check_mk_agent/spool
|
||||
scp /tmp/90000_checkpbs root@"$SOURCEHOST":/var/lib/check_mk_agent/spool || log "Fehler beim SCP des Monitoring-Outputs"
|
||||
}
|
||||
|
||||
|
||||
run_maintenance() {
|
||||
if [[ "$(date +%u)" == "$MAINTDAY" ]]; then
|
||||
log "Running maintenance..."
|
||||
@@ -122,26 +289,41 @@ run_maintenance() {
|
||||
}
|
||||
|
||||
run_scrub_stop_src() {
|
||||
ssh root@"$SOURCEHOST" 'for pool in $(zpool list -H -o name); do
|
||||
echo "⏹️ Stoppe Scrub auf Pool: $pool"
|
||||
zpool scrub -s "$pool"
|
||||
ssh -p "$SSHPORT" root@"$SOURCEHOST" 'for pool in $(zpool list -H -o name); do
|
||||
echo "Stoppe Scrub auf Pool: $pool"
|
||||
if zpool status "$pool" | grep -q "scrub in progress"; then
|
||||
if zpool scrub -s "$pool"; then
|
||||
echo "Scrub auf $pool gestoppt"
|
||||
else
|
||||
echo "Fehler beim Stoppen des Scrubs auf $pool"
|
||||
fi
|
||||
else
|
||||
echo "Kein aktiver Scrub auf $pool"
|
||||
fi
|
||||
done'
|
||||
}
|
||||
|
||||
run_scrub_stop_local() {
|
||||
for pool in $(zpool list -H -o name); do
|
||||
echo "⏹️ Stoppe Scrub auf Pool: $pool"
|
||||
if zpool scrub -s "$pool"; then
|
||||
echo "✔️ Scrub auf $pool gestoppt"
|
||||
echo "Stoppe Scrub auf Pool: $pool"
|
||||
if zpool status "$pool" | grep -q "scrub in progress"; then
|
||||
if zpool scrub -s "$pool"; then
|
||||
echo "Scrub auf $pool gestoppt"
|
||||
else
|
||||
echo "Fehler beim Stoppen des Scrubs auf $pool"
|
||||
fi
|
||||
else
|
||||
echo "❌ Fehler beim Stoppen des Scrubs auf $pool"
|
||||
echo "Kein aktiver Scrub auf $pool"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
shutdown_if_requested() {
|
||||
if [[ "$SHUTDOWN" == "yes" ]]; then
|
||||
log "SHUTDOWN-Variable: '${SHUTDOWN:-nicht gesetzt}'"
|
||||
#if [[ "${SHUTDOWN,,}" == "yes" ]]; then
|
||||
if [[ "$(echo "$SHUTDOWN" | tr '[:upper:]' '[:lower:]')" == "yes" ]]; then
|
||||
send_piggyback_data
|
||||
send_piggyback_data_external
|
||||
log "Shutting down now..."
|
||||
shutdown now
|
||||
else
|
||||
@@ -149,30 +331,102 @@ shutdown_if_requested() {
|
||||
fi
|
||||
}
|
||||
|
||||
send_piggyback_data_external() {
|
||||
if [[ "${EPIGGYBACK,,}" != "yes" ]]; then
|
||||
log "Externer Piggyback-Export deaktiviert."
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -z "$EPIGGYBACK_HOST" || -z "$EPIGGYBACK_PORT" ]]; then
|
||||
log "EPIGGYBACK_HOST oder EPIGGYBACK_PORT nicht gesetzt – Abbruch."
|
||||
return 1
|
||||
fi
|
||||
|
||||
local combined_host="miyagi-${SOURCEHOSTNAME}-$(hostname)"
|
||||
local filename="90000_${combined_host}_external"
|
||||
|
||||
log "Erzeuge externe Piggyback-Datei: $filename"
|
||||
|
||||
{
|
||||
echo "<<<<${combined_host}>>>>"
|
||||
/usr/bin/check_mk_agent
|
||||
echo "<<<<>>>>"
|
||||
} > "$filename"
|
||||
|
||||
if scp -P "$EPIGGYBACK_PORT" "$filename" "$EPIGGYBACK_HOST:/var/lib/check_mk_agent/spool/"; then
|
||||
log "Piggyback-Daten erfolgreich an $EPIGGYBACK_HOST gesendet."
|
||||
else
|
||||
log "Fehler beim Senden der Piggyback-Daten an $EPIGGYBACK_HOST"
|
||||
fi
|
||||
|
||||
rm -f "$filename"
|
||||
}
|
||||
|
||||
send_checkzfs_output_external() {
|
||||
if [[ "${ECHECKZFS,,}" != "yes" ]]; then
|
||||
log "Externer check_zfs-Export deaktiviert."
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -z "$ECHECKZFS_HOST" || -z "$ECHECKZFS_PORT" ]]; then
|
||||
log "ECHECKZFS_HOST oder ECHECKZFS_PORT nicht gesetzt – Abbruch."
|
||||
return 1
|
||||
fi
|
||||
|
||||
local checkfile="/tmp/90000_checkzfs_external"
|
||||
|
||||
log "Führe check_zfs aus und schreibe Output nach $checkfile"
|
||||
/usr/lib/nagios/plugins/check_zfs > "$checkfile" 2>&1 || log "check_zfs Befehl fehlgeschlagen"
|
||||
|
||||
log "Sende check_zfs-Daten an $ECHECKZFS_HOST..."
|
||||
if scp -P "$ECHECKZFS_PORT" "$checkfile" "$ECHECKZFS_HOST:/var/lib/check_mk_agent/spool/"; then
|
||||
log "Check_zfs-Daten erfolgreich an $ECHECKZFS_HOST gesendet."
|
||||
else
|
||||
log "Fehler beim Senden der Check_zfs-Daten an $ECHECKZFS_HOST"
|
||||
fi
|
||||
|
||||
rm -f "$checkfile"
|
||||
}
|
||||
|
||||
|
||||
main() {
|
||||
log "Backup-Routine startet in 60 Sekunden..."
|
||||
sleep 60
|
||||
log "Starting full backup routine..."
|
||||
|
||||
SOURCEHOSTNAME=$(ssh "$SOURCEHOST" hostname)
|
||||
|
||||
set_wol_g_enabled
|
||||
write_zsync_config
|
||||
run_zsync
|
||||
run_updates
|
||||
run_maintenance
|
||||
send_checkzfs_output_external
|
||||
run_scrub_stop_local
|
||||
run_scrub_stop_src
|
||||
run_pbs_backup
|
||||
if [[ "${BACKUPSERVER,,}" == "yes" ]]; then
|
||||
log "BACKUPSERVER ist aktiviert, führe Backup aus..."
|
||||
run_maintenance
|
||||
run_pbs_backup
|
||||
else
|
||||
log "BACKUPSERVER ist nicht aktiviert (BACKUPSERVER=$BACKUPSERVER), überspringe Backup."
|
||||
fi
|
||||
|
||||
run_remote_updates
|
||||
run_updates
|
||||
|
||||
shutdown_if_requested
|
||||
|
||||
}
|
||||
|
||||
# Funktionsbasierter Aufruf
|
||||
if [[ "${1:-}" == "help" ]]; then
|
||||
echo "Verfügbare Funktionen:"
|
||||
echo "Verfuegbare Funktionen:"
|
||||
declare -F | awk '{print " - " $3}' | grep -v "^ - _"
|
||||
exit 0
|
||||
elif [[ "${1:-}" =~ ^[a-zA-Z0-9_]+$ && "$(type -t "$1")" == "function" ]]; then
|
||||
FUNC="$1"
|
||||
shift
|
||||
"$@"
|
||||
"$FUNC" "$@"
|
||||
exit 0
|
||||
else
|
||||
main
|
||||
fi
|
||||
|
||||
+203
@@ -0,0 +1,203 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
LOG() {
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
|
||||
}
|
||||
|
||||
CONFIG_FILE="${1:-}"
|
||||
|
||||
if [[ -z "$CONFIG_FILE" ]]; then
|
||||
LOG "❌ Keine Konfigurationsdatei übergeben."
|
||||
echo "Usage: $0 /pfad/zur/config"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -f "$CONFIG_FILE" ]]; then
|
||||
LOG "❌ Konfigurationsdatei nicht gefunden: $CONFIG_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! bash -n "$CONFIG_FILE"; then
|
||||
LOG "❌ Syntaxfehler in der Konfigurationsdatei!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
source "$CONFIG_FILE"
|
||||
|
||||
REQUIRED_VARS=(
|
||||
SSHPORT
|
||||
BACKUPSERVER
|
||||
ZSYNC
|
||||
MAINTDAY
|
||||
SHUTDOWN
|
||||
UPDATES
|
||||
SOURCEHOST
|
||||
ZFSROOT
|
||||
ZFSSECOND
|
||||
ZFSTRGT
|
||||
ZPUSHTAG
|
||||
ZPUSHMINKEEP
|
||||
ZPUSHKEEP
|
||||
ZPUSHLABEL
|
||||
ZPUSHFILTER
|
||||
PBSHOST
|
||||
BACKUPSTORE
|
||||
BACKUPSTOREPBS
|
||||
BACKUPEXCLUDE
|
||||
REPLEXCLUDE
|
||||
)
|
||||
|
||||
MISSING=()
|
||||
for var in "${REQUIRED_VARS[@]}"; do
|
||||
if ! declare -p "$var" &>/dev/null || [[ -z "${!var}" ]]; then
|
||||
MISSING+=("$var")
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${#MISSING[@]} -gt 0 ]]; then
|
||||
LOG " Fehlende Variablen in Konfiguration:"
|
||||
for v in "${MISSING[@]}"; do echo " - $v"; done
|
||||
exit 1
|
||||
else
|
||||
LOG " Alle Variablen gesetzt."
|
||||
fi
|
||||
|
||||
if [[ ${#MISSING[@]} -gt 0 ]]; then
|
||||
LOG " Fehlende Variablen in Konfiguration:"
|
||||
for v in "${MISSING[@]}"; do echo " - $v"; done
|
||||
exit 1
|
||||
else
|
||||
LOG " Alle Variablen gesetzt."
|
||||
fi
|
||||
|
||||
# Prüfung, ob SHUTDOWN auch tatsächlich in der Datei definiert wurde
|
||||
if ! grep -qE '^\s*SHUTDOWN\s*=' "$CONFIG_FILE"; then
|
||||
LOG "Hinweis: Die Variable 'SHUTDOWN' ist zwar gesetzt, aber nicht direkt in der Konfigurationsdatei '$CONFIG_FILE' definiert."
|
||||
LOG " → Bitte prüfen, ob dies gewollt ist oder von einer übergeordneten Quelle stammt."
|
||||
fi
|
||||
|
||||
# Anzeigen, ob SHUTDOWN aktiv ist
|
||||
LOG "SHUTDOWN-Status: ${SHUTDOWN:-nicht gesetzt}"
|
||||
|
||||
case "${SHUTDOWN,,}" in
|
||||
yes)
|
||||
LOG "Nach dem Backup wird das System heruntergefahren."
|
||||
;;
|
||||
no)
|
||||
LOG "Kein automatischer Shutdown nach dem Backup."
|
||||
;;
|
||||
*)
|
||||
LOG "Unbekannter SHUTDOWN-Wert: '${SHUTDOWN}' , erwartet: 'yes' oder 'no'"
|
||||
;;
|
||||
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
|
||||
LOG " SSH-Verbindung zu $host erfolgreich."
|
||||
return 0
|
||||
else
|
||||
LOG " SSH-Verbindung zu $host fehlgeschlagen!"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_and_copy_ssh_key() {
|
||||
local host=$1
|
||||
local keyfile="$HOME/.ssh/id_rsa.pub"
|
||||
|
||||
if [[ ! -f "$keyfile" ]]; then
|
||||
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
|
||||
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"
|
||||
else
|
||||
LOG " SSH-Key nicht übertragen."
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
check_sshd_config_recommendation() {
|
||||
local host=$1
|
||||
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 "")
|
||||
|
||||
if [[ -z "$current_setting" ]]; then
|
||||
LOG " Keine explizite 'PermitRootLogin'-Einstellung gefunden."
|
||||
elif echo "$current_setting" | grep -qi "PermitRootLogin yes"; then
|
||||
LOG " Aktuell ist PermitRootLogin=YES erlaubt auf $host"
|
||||
LOG " Empfehlung: auf 'prohibit-password' umstellen."
|
||||
PERMITROOT_YES_HOSTS+=("$host")
|
||||
else
|
||||
LOG " PermitRootLogin-Einstellung ist: $current_setting"
|
||||
fi
|
||||
}
|
||||
|
||||
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
|
||||
LOG " $host: $line"
|
||||
done
|
||||
else
|
||||
LOG " 'pveversion' ist auf $host nicht verfügbar – kein Proxmox?"
|
||||
fi
|
||||
}
|
||||
|
||||
run_host_check() {
|
||||
local host=$1
|
||||
LOG ""
|
||||
LOG "=== Prüfung für Host: $host ==="
|
||||
if check_ssh_connection "$host"; then
|
||||
check_and_copy_ssh_key "$host"
|
||||
check_sshd_config_recommendation "$host"
|
||||
check_pveversion "$host"
|
||||
fi
|
||||
echo ""
|
||||
}
|
||||
|
||||
run_host_check "$SOURCEHOST"
|
||||
|
||||
if [[ "$BACKUPSERVER" == "yes" ]]; then
|
||||
run_host_check "$PBSHOST"
|
||||
else
|
||||
LOG " BACKUPSERVER ist deaktiviert PBSHOST wird übersprungen."
|
||||
fi
|
||||
|
||||
# NACHLAUF: Frage zur automatischen Änderung von PermitRootLogin
|
||||
if [[ ${#PERMITROOT_YES_HOSTS[@]} -gt 0 ]]; then
|
||||
echo ""
|
||||
echo " Die folgenden Hosts erlauben derzeit root-Login per Passwort:"
|
||||
for h in "${PERMITROOT_YES_HOSTS[@]}"; do
|
||||
echo " - $h"
|
||||
done
|
||||
|
||||
read -rp " Möchtest du PermitRootLogin auf diesen Hosts auf 'prohibit-password' setzen und sshd neustarten? [j/N] " change_ans
|
||||
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'"
|
||||
done
|
||||
else
|
||||
echo " Änderung von sshd_config übersprungen."
|
||||
fi
|
||||
fi
|
||||
Reference in New Issue
Block a user