Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d050cbedf | ||
|
|
14019487b3 | ||
|
|
0141cdc4c7 | ||
|
|
cbef884db8 | ||
|
|
d83c3113f8 | ||
|
|
1619f22f18 | ||
|
|
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 | ||
|
|
b0e336279b | ||
|
|
f775f7ed4b | ||
|
|
22fc8bc6fc |
No files matched your search
@@ -0,0 +1,195 @@
|
|||||||
|
# v3 – Dev Log
|
||||||
|
|
||||||
|
## 2026-06-19 00:56 – 00:58 (1m)
|
||||||
|
**Beschreibung:** Claude Code Session
|
||||||
|
**Projekt:** miyagi-backup
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
Keine Commits in dieser Session.
|
||||||
|
|
||||||
|
### Geänderte Dateien
|
||||||
|
- config.example | 2 +-
|
||||||
|
|
||||||
|
---
|
||||||
|
## 2026-06-19 01:01 – 01:05 (4m)
|
||||||
|
**Beschreibung:** Claude Code Session
|
||||||
|
**Projekt:** v3
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
Keine Commits in dieser Session.
|
||||||
|
|
||||||
|
### Geänderte Dateien
|
||||||
|
- config.example | 2 +-
|
||||||
|
|
||||||
|
---
|
||||||
|
## 2026-06-19 01:06 – 01:07 (0m)
|
||||||
|
**Beschreibung:** Claude Code Session
|
||||||
|
**Projekt:** v3
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
Keine Commits in dieser Session.
|
||||||
|
|
||||||
|
### Geänderte Dateien
|
||||||
|
- config.example | 2 +-
|
||||||
|
|
||||||
|
---
|
||||||
|
## 2026-06-19 01:26 – 01:28 (2m)
|
||||||
|
**Beschreibung:** Claude Code Session
|
||||||
|
**Projekt:** v3
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
Keine Commits in dieser Session.
|
||||||
|
|
||||||
|
### Geänderte Dateien
|
||||||
|
- config.example | 2 +-
|
||||||
|
|
||||||
|
---
|
||||||
|
## 2026-06-19 01:32 – 01:33 (0m)
|
||||||
|
**Beschreibung:** Claude Code Session
|
||||||
|
**Projekt:** v3
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
Keine Commits in dieser Session.
|
||||||
|
|
||||||
|
### Geänderte Dateien
|
||||||
|
- config.example | 2 +-
|
||||||
|
|
||||||
|
---
|
||||||
|
## 2026-06-19 01:40 – 01:42 (2m)
|
||||||
|
**Beschreibung:** Claude Code Session
|
||||||
|
**Projekt:** v3
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
Keine Commits in dieser Session.
|
||||||
|
|
||||||
|
### Geänderte Dateien
|
||||||
|
- config.example | 2 +-
|
||||||
|
|
||||||
|
---
|
||||||
|
## 2026-06-19 01:44 – 01:47 (2m)
|
||||||
|
**Beschreibung:** Claude Code Session
|
||||||
|
**Projekt:** v3
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
Keine Commits in dieser Session.
|
||||||
|
|
||||||
|
### Geänderte Dateien
|
||||||
|
- config.example | 2 +-
|
||||||
|
|
||||||
|
---
|
||||||
|
## 2026-06-19 01:48 – 01:48 (0m)
|
||||||
|
**Beschreibung:** Claude Code Session
|
||||||
|
**Projekt:** v3
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
Keine Commits in dieser Session.
|
||||||
|
|
||||||
|
### Geänderte Dateien
|
||||||
|
- config.example | 2 +-
|
||||||
|
|
||||||
|
---
|
||||||
|
## 2026-06-19 01:49 – 02:08 (18m)
|
||||||
|
**Beschreibung:** Claude Code Session
|
||||||
|
**Projekt:** v3
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
Keine Commits in dieser Session.
|
||||||
|
|
||||||
|
### Geänderte Dateien
|
||||||
|
- config.example | 2 +-
|
||||||
|
|
||||||
|
---
|
||||||
|
## 2026-06-19 02:08 – 02:08 (0m)
|
||||||
|
**Beschreibung:** Claude Code Session
|
||||||
|
**Projekt:** v3
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
Keine Commits in dieser Session.
|
||||||
|
|
||||||
|
### Geänderte Dateien
|
||||||
|
- config.example | 2 +-
|
||||||
|
|
||||||
|
---
|
||||||
|
## 2026-06-19 02:09 – 02:10 (0m)
|
||||||
|
**Beschreibung:** Claude Code Session
|
||||||
|
**Projekt:** v3
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
Keine Commits in dieser Session.
|
||||||
|
|
||||||
|
### Geänderte Dateien
|
||||||
|
- config.example | 2 +-
|
||||||
|
|
||||||
|
---
|
||||||
|
## 2026-06-19 02:11 – 02:15 (3m)
|
||||||
|
**Beschreibung:** Claude Code Session
|
||||||
|
**Projekt:** v3
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
Keine Commits in dieser Session.
|
||||||
|
|
||||||
|
### Geänderte Dateien
|
||||||
|
- config.example | 2 +-
|
||||||
|
|
||||||
|
---
|
||||||
|
## 2026-06-19 02:16 – 02:16 (0m)
|
||||||
|
**Beschreibung:** Claude Code Session
|
||||||
|
**Projekt:** v3
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
Keine Commits in dieser Session.
|
||||||
|
|
||||||
|
### Geänderte Dateien
|
||||||
|
- config.example | 2 +-
|
||||||
|
|
||||||
|
---
|
||||||
|
## 2026-07-07 – Pre-Shutdown-Hooks + Installpfade
|
||||||
|
|
||||||
|
**Feature:** `run_pre_shutdown_hooks()` eingebaut, aufgerufen in `shutdown_now()` nach Piggyback/CheckZFS, vor 60s-Sleep.
|
||||||
|
|
||||||
|
**Hook-Verzeichnis:** `/etc/miyagi-backup/hooks.d/pre-shutdown/`
|
||||||
|
- Verzeichnis fehlt oder leer → still übersprungen
|
||||||
|
- Nur `*.sh` mit `chmod +x` werden ausgeführt
|
||||||
|
- Alphabetisch sortiert
|
||||||
|
- Hook-Fehler → WARNUNG im Log, Shutdown läuft weiter
|
||||||
|
|
||||||
|
**Installpfade festgelegt:**
|
||||||
|
- Skripte: `/opt/miyagi-backup/`
|
||||||
|
- Konfigs: `/etc/miyagi-backup/`
|
||||||
|
- Hooks: `/etc/miyagi-backup/hooks.d/pre-shutdown/`
|
||||||
|
- Symlink: `/usr/local/bin/miyagi-backup` → `/opt/miyagi-backup/miyagi-backup.sh`
|
||||||
|
|
||||||
|
---
|
||||||
|
## 2026-07-16 14:13 – 14:13 (0m)
|
||||||
|
**Beschreibung:** Claude Code Session
|
||||||
|
**Projekt:** v3
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
Keine Commits in dieser Session.
|
||||||
|
|
||||||
|
### Geänderte Dateien
|
||||||
|
- miyagi-check.sh | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
|
||||||
|
|
||||||
|
---
|
||||||
|
## 2026-07-16 14:16 – 14:48 (32m)
|
||||||
|
**Beschreibung:** Claude Code Session
|
||||||
|
**Projekt:** v3
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
Keine Commits in dieser Session.
|
||||||
|
|
||||||
|
### Geänderte Dateien
|
||||||
|
- miyagi-check.sh | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
|
||||||
|
|
||||||
|
---
|
||||||
|
## 2026-07-16 14:49 – 14:51 (1m)
|
||||||
|
**Beschreibung:** Claude Code Session
|
||||||
|
**Projekt:** v3
|
||||||
|
|
||||||
|
### Commits
|
||||||
|
Keine Commits in dieser Session.
|
||||||
|
|
||||||
|
### Geänderte Dateien
|
||||||
|
- miyagi-check.sh | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
|
||||||
|
|
||||||
|
---
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
🧪 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
|
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
#Edit all Variables for best Experience
|
||||||
|
|
||||||
|
UPDATES='yes' # Proxmox VE und PBS Updates nach dem Lauf
|
||||||
|
SHUTDOWN='no' # System nach Ausführung herunterfahren?
|
||||||
|
DYNROUTE='yes' # DYNroute ja oder nein?
|
||||||
|
DDNS_GATEWAY='192.168.66.1' # DYNDNS Gateway
|
||||||
|
DDNS_SERVER='1.1.1.1' #DNS Server extern
|
||||||
|
REBOOT='no' # Reboot nach Update?
|
||||||
|
|
||||||
|
# Quelle (Proxmox VE System, das gesichert wird)
|
||||||
|
SOURCEPORT='22' # SSH-Port, normalerweise 22
|
||||||
|
SOURCEHOST='192.168.50.200' # IP des Quell-Proxmox-Servers
|
||||||
|
SOURCEUSER='root' # SSH-User für SOURCEHOST
|
||||||
|
|
||||||
|
# Replikation (ZFS)
|
||||||
|
ZFSTRGT='rpool-ssd1/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
|
||||||
|
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.)
|
||||||
|
|
||||||
|
# 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' # SSH-Port PBS
|
||||||
|
PBSUSER='root' # SSH-User für PBSHOST
|
||||||
|
PBSBACKUP_STATUS='86400' # Warnung ab 24h (86400s)
|
||||||
|
PBS_REPO_USER='root@pam' # PBS-User oder API-Token-ID (z.B. 'user@pbs!tokenname') für write_pbs_status
|
||||||
|
PBS_PASSWORD='' # Passwort oder API-Token-Secret zu PBS_REPO_USER (write_pbs_status)
|
||||||
|
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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
EPIGGYBACK_USER='root' # SSH-User für EPIGGYBACK_HOST
|
||||||
|
|
||||||
|
# External Checkzfs Host
|
||||||
|
ECHECKZFS='no' # CheckZFS-Daten an externen Monitoring-Host senden?
|
||||||
|
ECHECKZFS_PORT='2222' # SSH-Port für ECHECKZFS_HOST
|
||||||
|
ECHECKZFS_HOST='192.168.50.210' # Monitoring-Zielhost für check_zfs
|
||||||
|
ECHECKZFS_USER='root' # SSH-User für ECHECKZFS_HOST
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Beispiel Pre-Shutdown-Hook für miyagi-backup
|
||||||
|
#
|
||||||
|
# Ablage: /etc/miyagi-backup/hooks.d/pre-shutdown/
|
||||||
|
# Ausführung: chmod +x <hookname>.sh
|
||||||
|
# Reihenfolge: alphabetisch (01-foo.sh, 02-bar.sh, ...)
|
||||||
|
# Fehlerverhalten: Exit != 0 erzeugt WARNUNG im Log, Shutdown läuft weiter
|
||||||
|
#
|
||||||
|
# Dieser Hook wird vor dem 60s-Countdown in shutdown_now() ausgeführt.
|
||||||
|
# Hinweis: eigene sleep-Aufrufe addieren sich zum 60s-Countdown dazu.
|
||||||
|
|
||||||
|
# ── Beispiel 1: Monitoring-Agent vor Shutdown reporten ───────────────────────
|
||||||
|
#
|
||||||
|
# if [ -x /usr/local/bin/patchmon-agent ]; then
|
||||||
|
# /usr/local/bin/patchmon-agent report
|
||||||
|
# fi
|
||||||
|
|
||||||
|
# ── Beispiel 2: CheckMK-Agent aktualisieren ───────────────────────────────────
|
||||||
|
#
|
||||||
|
# if [ -x /usr/bin/cmk-agent-update ]; then
|
||||||
|
# /usr/bin/cmk-agent-update
|
||||||
|
# fi
|
||||||
|
|
||||||
|
# ── Beispiel 3: Dienst neu starten (nur wenn installiert) ────────────────────
|
||||||
|
#
|
||||||
|
# if systemctl list-unit-files wazuh-agent.service &>/dev/null; then
|
||||||
|
# systemctl restart wazuh-agent.service
|
||||||
|
# fi
|
||||||
|
|
||||||
|
# ── Beispiel 4: Eigenes Skript aufrufen ───────────────────────────────────────
|
||||||
|
#
|
||||||
|
# /opt/myscript/notify-shutdown.sh
|
||||||
|
|
||||||
|
exit 0
|
||||||
+868
-107
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,293 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# miyagi-backup Installer v3
|
||||||
|
set -uo pipefail
|
||||||
|
|
||||||
|
FORCE_YES=0
|
||||||
|
DRY_RUN=0
|
||||||
|
DEV_MODE=0
|
||||||
|
CONFIG_FILE=""
|
||||||
|
INSTALL_DIR="/opt/miyagi-backup"
|
||||||
|
CONFIG_DIR="/etc/miyagi-backup"
|
||||||
|
HOOKS_DIR="${CONFIG_DIR}/hooks.d/pre-shutdown"
|
||||||
|
SYMLINK="/usr/local/bin/miyagi-backup"
|
||||||
|
|
||||||
|
GITHUB_BASE="https://raw.githubusercontent.com/bashclub/miyagi-backup/main"
|
||||||
|
GITEA_BASE="https://gitea.perlbach24.de/scripte/miyagi-backup/raw/branch/main"
|
||||||
|
|
||||||
|
CHECKZFS_URL="https://gitea.perlbach24.de/scripte/check-zfs-replication/raw/branch/main/checkzfs.py"
|
||||||
|
CHECK_SNAPSHOT_AGE_URL="https://gitea.perlbach24.de/scripte/check-zfs-replication/raw/branch/main/check-snapshot-age"
|
||||||
|
CLEANSNAPS_URL="https://raw.githubusercontent.com/bashclub/zfs-housekeeping/refs/heads/main/cleansnaps.sh"
|
||||||
|
DISK_SMART_INFO_URL="https://raw.githubusercontent.com/bashclub/checkmk-smart/main/disk_smart_info.py"
|
||||||
|
|
||||||
|
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; NC='\033[0m'
|
||||||
|
ok() { echo -e "${GREEN}[OK]${NC} $*"; }
|
||||||
|
info() { echo -e "${BLUE}[..]${NC} $*"; }
|
||||||
|
warn() { echo -e "${YELLOW}[!!]${NC} $*"; }
|
||||||
|
die() { echo -e "${RED}[ERR]${NC} $*" >&2; exit 1; }
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: $0 [OPTIONS]
|
||||||
|
|
||||||
|
-c <file> Konfigurationsdatei laden (für SSH-Check + ZFS-Tagging)
|
||||||
|
--yes Keine Rückfragen
|
||||||
|
--dry-run Zeigt nur was gemacht würde
|
||||||
|
--dev Installiere von Gitea (dev) statt GitHub (stable)
|
||||||
|
--help Diese Hilfe
|
||||||
|
EOF
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
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 ;;
|
||||||
|
--dev) DEV_MODE=1; shift ;;
|
||||||
|
--help) usage ;;
|
||||||
|
*) die "Unbekannter Parameter: $1" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -n "$CONFIG_FILE" ]]; then
|
||||||
|
[[ ! -f "$CONFIG_FILE" ]] && die "Konfigurationsdatei nicht gefunden: $CONFIG_FILE"
|
||||||
|
bash -n "$CONFIG_FILE" || die "Syntaxfehler in $CONFIG_FILE"
|
||||||
|
source "$CONFIG_FILE"
|
||||||
|
SOURCEUSER="${SOURCEUSER:-root}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
run() {
|
||||||
|
if [[ "$DRY_RUN" -eq 1 ]]; then
|
||||||
|
echo "[DRY-RUN] $*"
|
||||||
|
else
|
||||||
|
"$@"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
confirm() {
|
||||||
|
[[ "$FORCE_YES" -eq 1 ]] && return 0
|
||||||
|
while true; do
|
||||||
|
read -rp "$1 [j/N]: " yn
|
||||||
|
case "$yn" in
|
||||||
|
[JjYy]*) return 0 ;;
|
||||||
|
[Nn]*|"") return 1 ;;
|
||||||
|
*) echo "Bitte j oder n eingeben." ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_dialog() {
|
||||||
|
if ! command -v dialog &>/dev/null; then
|
||||||
|
info "Installiere dialog..."
|
||||||
|
run apt-get install -y -qq dialog || die "dialog konnte nicht installiert werden"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
get_base_url() {
|
||||||
|
[[ "$DEV_MODE" -eq 1 ]] && echo "$GITEA_BASE" || echo "$GITHUB_BASE"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Installationsschritte ─────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
install_miyagi() {
|
||||||
|
local base
|
||||||
|
base="$(get_base_url)"
|
||||||
|
local source_label
|
||||||
|
[[ "$DEV_MODE" -eq 1 ]] && source_label="Gitea (dev)" || source_label="GitHub (stable)"
|
||||||
|
|
||||||
|
info "Installiere miyagi-backup von $source_label..."
|
||||||
|
|
||||||
|
run mkdir -p "$INSTALL_DIR"
|
||||||
|
run mkdir -p "$CONFIG_DIR"
|
||||||
|
run mkdir -p "$HOOKS_DIR"
|
||||||
|
|
||||||
|
run curl -fsSL "${base}/miyagi-backup.sh" -o "${INSTALL_DIR}/miyagi-backup.sh"
|
||||||
|
run chmod +x "${INSTALL_DIR}/miyagi-backup.sh"
|
||||||
|
|
||||||
|
# config.example nur holen, nie bestehende Config überschreiben
|
||||||
|
run curl -fsSL "${base}/config.example" -o "${CONFIG_DIR}/config.example"
|
||||||
|
|
||||||
|
# Example-Hook kopieren (nicht ausführbar = inaktiv bis User chmod +x setzt)
|
||||||
|
run curl -fsSL "${base}/hooks.d/pre-shutdown/example-hook.sh" \
|
||||||
|
-o "${HOOKS_DIR}/example-hook.sh"
|
||||||
|
|
||||||
|
# Symlink
|
||||||
|
run ln -sf "${INSTALL_DIR}/miyagi-backup.sh" "$SYMLINK"
|
||||||
|
|
||||||
|
ok "miyagi-backup installiert: ${INSTALL_DIR}/miyagi-backup.sh"
|
||||||
|
ok "Symlink: $SYMLINK"
|
||||||
|
ok "Config-Verzeichnis: $CONFIG_DIR"
|
||||||
|
ok "Hook-Verzeichnis: $HOOKS_DIR"
|
||||||
|
}
|
||||||
|
|
||||||
|
install_checkzfs() {
|
||||||
|
info "Installiere checkzfs..."
|
||||||
|
run curl -fsSL "$CHECKZFS_URL" -o /usr/local/bin/checkzfs
|
||||||
|
run chmod +x /usr/local/bin/checkzfs
|
||||||
|
ok "checkzfs installiert"
|
||||||
|
}
|
||||||
|
|
||||||
|
install_check_snapshot_age() {
|
||||||
|
info "Installiere check-snapshot-age..."
|
||||||
|
run curl -fsSL "$CHECK_SNAPSHOT_AGE_URL" -o /usr/local/bin/check-snapshot-age
|
||||||
|
run chmod +x /usr/local/bin/check-snapshot-age
|
||||||
|
ok "check-snapshot-age installiert"
|
||||||
|
}
|
||||||
|
|
||||||
|
install_cleansnaps() {
|
||||||
|
info "Installiere cleansnaps..."
|
||||||
|
run curl -fsSL "$CLEANSNAPS_URL" -o /usr/local/bin/cleansnaps
|
||||||
|
run chmod +x /usr/local/bin/cleansnaps
|
||||||
|
ok "cleansnaps installiert"
|
||||||
|
}
|
||||||
|
|
||||||
|
install_disk_smart_info() {
|
||||||
|
info "Installiere disk_smart_info..."
|
||||||
|
run mkdir -p /usr/lib/check_mk_agent/plugins
|
||||||
|
run curl -fsSL "$DISK_SMART_INFO_URL" -o /usr/lib/check_mk_agent/plugins/disk_smart_info
|
||||||
|
run chmod +x /usr/lib/check_mk_agent/plugins/disk_smart_info
|
||||||
|
ok "disk_smart_info installiert"
|
||||||
|
}
|
||||||
|
|
||||||
|
install_ethtool() {
|
||||||
|
info "Installiere ethtool..."
|
||||||
|
run apt-get install -y -qq ethtool
|
||||||
|
ok "ethtool installiert"
|
||||||
|
}
|
||||||
|
|
||||||
|
check_ssh() {
|
||||||
|
[[ -z "${SOURCEHOST:-}" ]] && warn "Kein SOURCEHOST in Config – SSH-Check übersprungen" && return
|
||||||
|
info "Teste SSH-Verbindung zu ${SOURCEUSER}@${SOURCEHOST}:${SOURCEPORT}..."
|
||||||
|
|
||||||
|
if ssh -p "${SOURCEPORT:-22}" -o BatchMode=yes -o ConnectTimeout=5 \
|
||||||
|
"${SOURCEUSER}@${SOURCEHOST}" "echo ok" &>/dev/null; then
|
||||||
|
ok "SSH-Verbindung via Schlüssel funktioniert"
|
||||||
|
else
|
||||||
|
warn "Keine schlüsselbasierte SSH-Verbindung möglich"
|
||||||
|
if confirm "SSH-Schlüssel jetzt auf ${SOURCEHOST} kopieren (ssh-copy-id)?"; then
|
||||||
|
run ssh-copy-id -p "${SOURCEPORT:-22}" "${SOURCEUSER}@${SOURCEHOST}"
|
||||||
|
ok "Schlüssel kopiert – bitte Installer erneut starten zum Verifizieren"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
select_zfs_pools() {
|
||||||
|
[[ -z "${SOURCEHOST:-}" ]] && warn "Kein SOURCEHOST – ZFS-Tagging übersprungen" && return
|
||||||
|
|
||||||
|
info "Lade ZFS-Datasets von ${SOURCEHOST}..."
|
||||||
|
local local_hostname remote_hostname tag_key tag_value
|
||||||
|
local_hostname="$(hostname -s)"
|
||||||
|
remote_hostname="$(ssh -p "${SOURCEPORT:-22}" "${SOURCEUSER}@${SOURCEHOST}" "hostname -s" 2>/dev/null)" \
|
||||||
|
|| { warn "SSH-Verbindung fehlgeschlagen – ZFS-Tagging übersprungen"; return; }
|
||||||
|
|
||||||
|
tag_key="bashclub:miyagi-${remote_hostname}-${local_hostname}"
|
||||||
|
tag_value="subvols"
|
||||||
|
|
||||||
|
mapfile -t pools < <(ssh -p "${SOURCEPORT:-22}" "${SOURCEUSER}@${SOURCEHOST}" \
|
||||||
|
"zfs list -H -o name" 2>/dev/null | \
|
||||||
|
grep -E '/(vm|subvol)-' | \
|
||||||
|
grep -viE 'repl|replica' | \
|
||||||
|
sed 's:/[^/]*$::' | \
|
||||||
|
sort -u)
|
||||||
|
|
||||||
|
if [[ ${#pools[@]} -eq 0 ]]; then
|
||||||
|
warn "Keine geeigneten ZFS-Datasets gefunden"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local options=()
|
||||||
|
for pool in "${pools[@]}"; do
|
||||||
|
local tag status
|
||||||
|
tag="$(ssh -p "${SOURCEPORT:-22}" "${SOURCEUSER}@${SOURCEHOST}" \
|
||||||
|
zfs get -H -o value "$tag_key" "$pool" 2>/dev/null)"
|
||||||
|
[[ "$tag" == "$tag_value" ]] && status="on" || status="off"
|
||||||
|
options+=("$pool" "" "$status")
|
||||||
|
done
|
||||||
|
|
||||||
|
local selected
|
||||||
|
selected=$(dialog --clear \
|
||||||
|
--backtitle "miyagi-backup Installer" \
|
||||||
|
--title "ZFS Pools taggen" \
|
||||||
|
--checklist "Datasets für Replikation auswählen:" 20 78 12 \
|
||||||
|
"${options[@]}" \
|
||||||
|
3>&1 1>&2 2>&3)
|
||||||
|
clear
|
||||||
|
[[ $? -ne 0 ]] && info "ZFS-Tagging abgebrochen" && return
|
||||||
|
|
||||||
|
local selected_array=()
|
||||||
|
read -ra selected_array <<< "$selected"
|
||||||
|
|
||||||
|
for pool in "${pools[@]}"; do
|
||||||
|
local is_selected=0
|
||||||
|
local prev_status="off"
|
||||||
|
for ((i=0; i<${#options[@]}; i+=3)); do
|
||||||
|
[[ "${options[i]}" == "$pool" ]] && prev_status="${options[i+2]}" && break
|
||||||
|
done
|
||||||
|
for sel in "${selected_array[@]}"; do
|
||||||
|
[[ "$sel" == "\"$pool\"" || "$sel" == "$pool" ]] && is_selected=1 && break
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ "$is_selected" -eq 1 && "$prev_status" == "off" ]]; then
|
||||||
|
info "Tagge $pool"
|
||||||
|
run ssh -p "${SOURCEPORT:-22}" "${SOURCEUSER}@${SOURCEHOST}" \
|
||||||
|
zfs set "${tag_key}=${tag_value}" "$pool"
|
||||||
|
elif [[ "$is_selected" -eq 0 && "$prev_status" == "on" ]]; then
|
||||||
|
info "Entferne Tag von $pool"
|
||||||
|
run ssh -p "${SOURCEPORT:-22}" "${SOURCEUSER}@${SOURCEHOST}" \
|
||||||
|
zfs inherit "$tag_key" "$pool"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
ok "ZFS-Tagging abgeschlossen"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Hauptmenü ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
main() {
|
||||||
|
[[ $EUID -ne 0 ]] && die "Bitte als root ausführen"
|
||||||
|
|
||||||
|
ensure_dialog
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo " ╔══════════════════════════════════════╗"
|
||||||
|
echo " ║ miyagi-backup Installer v3 ║"
|
||||||
|
echo " ╚══════════════════════════════════════╝"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
local choices
|
||||||
|
choices=$(dialog --clear \
|
||||||
|
--backtitle "miyagi-backup Installer v3" \
|
||||||
|
--title "Komponenten auswählen" \
|
||||||
|
--checklist "Was soll installiert werden?" 22 65 12 \
|
||||||
|
"miyagi" "miyagi-backup.sh + Verzeichnisse + Symlink" on \
|
||||||
|
"checkzfs" "checkzfs (ZFS-Replikationsprüfung)" on \
|
||||||
|
"snapage" "check-snapshot-age" on \
|
||||||
|
"cleansnaps" "cleansnaps (ZFS-Snapshot-Housekeeping)" on \
|
||||||
|
"smartinfo" "disk_smart_info (CheckMK Plugin)" on \
|
||||||
|
"ethtool" "ethtool (WOL-Unterstützung)" off \
|
||||||
|
"ssh" "SSH-Verbindung prüfen / Schlüssel kopieren" on \
|
||||||
|
"zfstag" "ZFS-Pools taggen (benötigt Config -c)" off \
|
||||||
|
3>&1 1>&2 2>&3)
|
||||||
|
clear
|
||||||
|
|
||||||
|
[[ $? -ne 0 ]] && echo "Abgebrochen." && exit 0
|
||||||
|
[[ -z "$choices" ]] && echo "Nichts ausgewählt." && exit 0
|
||||||
|
|
||||||
|
[[ "$choices" == *'"miyagi"'* || "$choices" == *'miyagi'* ]] && install_miyagi
|
||||||
|
[[ "$choices" == *'"checkzfs"'* || "$choices" == *'checkzfs'* ]] && install_checkzfs
|
||||||
|
[[ "$choices" == *'"snapage"'* || "$choices" == *'snapage'* ]] && install_check_snapshot_age
|
||||||
|
[[ "$choices" == *'"cleansnaps"'* || "$choices" == *'cleansnaps'* ]] && install_cleansnaps
|
||||||
|
[[ "$choices" == *'"smartinfo"'* || "$choices" == *'smartinfo'* ]] && install_disk_smart_info
|
||||||
|
[[ "$choices" == *'"ethtool"'* || "$choices" == *'ethtool'* ]] && install_ethtool
|
||||||
|
[[ "$choices" == *'"ssh"'* || "$choices" == *'ssh'* ]] && check_ssh
|
||||||
|
[[ "$choices" == *'"zfstag"'* || "$choices" == *'zfstag'* ]] && select_zfs_pools
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
ok "Installation abgeschlossen."
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_args "$@"
|
||||||
|
main
|
||||||
@@ -0,0 +1,168 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# miyagi-backup Updater v3
|
||||||
|
set -uo pipefail
|
||||||
|
|
||||||
|
DEV_MODE=0
|
||||||
|
INSTALL_DIR="/opt/miyagi-backup"
|
||||||
|
CONFIG_DIR="/etc/miyagi-backup"
|
||||||
|
HOOKS_DIR="${CONFIG_DIR}/hooks.d/pre-shutdown"
|
||||||
|
SYMLINK="/usr/local/bin/miyagi-backup"
|
||||||
|
|
||||||
|
GITHUB_BASE="https://raw.githubusercontent.com/bashclub/miyagi-backup/main"
|
||||||
|
GITEA_BASE="https://gitea.perlbach24.de/scripte/miyagi-backup/raw/branch/main"
|
||||||
|
|
||||||
|
CHECKZFS_URL="https://gitea.perlbach24.de/scripte/check-zfs-replication/raw/branch/main/checkzfs.py"
|
||||||
|
CHECK_SNAPSHOT_AGE_URL="https://gitea.perlbach24.de/scripte/check-zfs-replication/raw/branch/main/check-snapshot-age"
|
||||||
|
CLEANSNAPS_URL="https://raw.githubusercontent.com/bashclub/zfs-housekeeping/refs/heads/main/cleansnaps.sh"
|
||||||
|
DISK_SMART_INFO_URL="https://raw.githubusercontent.com/bashclub/checkmk-smart/main/disk_smart_info.py"
|
||||||
|
|
||||||
|
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; NC='\033[0m'
|
||||||
|
ok() { echo -e "${GREEN}[OK]${NC} $*"; }
|
||||||
|
info() { echo -e "${BLUE}[..]${NC} $*"; }
|
||||||
|
warn() { echo -e "${YELLOW}[!!]${NC} $*"; }
|
||||||
|
die() { echo -e "${RED}[ERR]${NC} $*" >&2; exit 1; }
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: $0 [--dev]
|
||||||
|
|
||||||
|
--dev Update von Gitea (dev) statt GitHub (stable)
|
||||||
|
--help Diese Hilfe
|
||||||
|
EOF
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_args() {
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--dev) DEV_MODE=1; shift ;;
|
||||||
|
--help) usage ;;
|
||||||
|
*) die "Unbekannter Parameter: $1" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
get_base_url() {
|
||||||
|
[[ "$DEV_MODE" -eq 1 ]] && echo "$GITEA_BASE" || echo "$GITHUB_BASE"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Self-Update ───────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
self_update() {
|
||||||
|
local base
|
||||||
|
base="$(get_base_url)"
|
||||||
|
local self="${INSTALL_DIR}/miyagi-update.sh"
|
||||||
|
|
||||||
|
if [[ -f "$self" ]] && command -v curl >/dev/null; then
|
||||||
|
curl -fsSL "${base}/miyagi-update.sh" -o "${self}.new" 2>/dev/null \
|
||||||
|
&& mv "${self}.new" "$self" \
|
||||||
|
&& chmod +x "$self" \
|
||||||
|
&& info "Updater aktualisiert" \
|
||||||
|
|| rm -f "${self}.new"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── miyagi-backup.sh updaten ─────────────────────────────────────────────────
|
||||||
|
|
||||||
|
update_miyagi() {
|
||||||
|
local base
|
||||||
|
base="$(get_base_url)"
|
||||||
|
local source_label
|
||||||
|
[[ "$DEV_MODE" -eq 1 ]] && source_label="Gitea (dev)" || source_label="GitHub (stable)"
|
||||||
|
|
||||||
|
info "Aktualisiere miyagi-backup.sh von $source_label..."
|
||||||
|
|
||||||
|
if [[ ! -d "$INSTALL_DIR" ]]; then
|
||||||
|
warn "Installverzeichnis $INSTALL_DIR fehlt – bitte zuerst miyagi-install.sh ausführen"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
curl -fsSL "${base}/miyagi-backup.sh" -o "${INSTALL_DIR}/miyagi-backup.sh.new" || {
|
||||||
|
warn "Download fehlgeschlagen – miyagi-backup.sh bleibt unverändert"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
mv "${INSTALL_DIR}/miyagi-backup.sh.new" "${INSTALL_DIR}/miyagi-backup.sh"
|
||||||
|
chmod +x "${INSTALL_DIR}/miyagi-backup.sh"
|
||||||
|
|
||||||
|
# Symlink sicherstellen
|
||||||
|
ln -sf "${INSTALL_DIR}/miyagi-backup.sh" "$SYMLINK"
|
||||||
|
|
||||||
|
# config.example aktualisieren (nie .conf überschreiben)
|
||||||
|
curl -fsSL "${base}/config.example" -o "${CONFIG_DIR}/config.example.new" 2>/dev/null \
|
||||||
|
&& mv "${CONFIG_DIR}/config.example.new" "${CONFIG_DIR}/config.example" \
|
||||||
|
|| warn "config.example konnte nicht aktualisiert werden"
|
||||||
|
|
||||||
|
# Hooks-Verzeichnis sicherstellen
|
||||||
|
mkdir -p "$HOOKS_DIR"
|
||||||
|
|
||||||
|
# Example-Hook aktualisieren (nicht ausführbar = bleibt inaktiv)
|
||||||
|
curl -fsSL "${base}/hooks.d/pre-shutdown/example-hook.sh" \
|
||||||
|
-o "${HOOKS_DIR}/example-hook.sh" 2>/dev/null \
|
||||||
|
&& info "example-hook.sh aktualisiert" \
|
||||||
|
|| warn "example-hook.sh konnte nicht aktualisiert werden"
|
||||||
|
|
||||||
|
ok "miyagi-backup.sh aktualisiert"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Abhängigkeiten updaten (nur wenn bereits installiert) ─────────────────────
|
||||||
|
|
||||||
|
update_dep() {
|
||||||
|
local name="$1"
|
||||||
|
local url="$2"
|
||||||
|
local target="$3"
|
||||||
|
|
||||||
|
if [[ ! -f "$target" ]]; then
|
||||||
|
info "$name nicht installiert – übersprungen (install mit miyagi-install.sh)"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
info "Aktualisiere $name..."
|
||||||
|
curl -fsSL "$url" -o "${target}.new" 2>/dev/null || {
|
||||||
|
warn "$name Download fehlgeschlagen – bleibt unverändert"
|
||||||
|
rm -f "${target}.new"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
mv "${target}.new" "$target"
|
||||||
|
chmod +x "$target"
|
||||||
|
ok "$name aktualisiert"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Status-Zusammenfassung ────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
print_status() {
|
||||||
|
echo ""
|
||||||
|
echo " ┌──────────────────────────────────────────┐"
|
||||||
|
printf " │ %-40s│\n" "miyagi-backup $([ -f "${INSTALL_DIR}/miyagi-backup.sh" ] && echo "✓ installiert" || echo "✗ fehlt")"
|
||||||
|
printf " │ %-40s│\n" "checkzfs $(command -v checkzfs &>/dev/null && echo "✓" || echo "✗ nicht installiert")"
|
||||||
|
printf " │ %-40s│\n" "check-snap-age $(command -v check-snapshot-age &>/dev/null && echo "✓" || echo "✗ nicht installiert")"
|
||||||
|
printf " │ %-40s│\n" "cleansnaps $(command -v cleansnaps &>/dev/null && echo "✓" || echo "✗ nicht installiert")"
|
||||||
|
printf " │ %-40s│\n" "ethtool $(command -v ethtool &>/dev/null && echo "✓" || echo "✗ nicht installiert")"
|
||||||
|
echo " └──────────────────────────────────────────┘"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Main ──────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
main() {
|
||||||
|
[[ $EUID -ne 0 ]] && die "Bitte als root ausführen"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo " ╔══════════════════════════════════════╗"
|
||||||
|
echo " ║ miyagi-backup Updater v3 ║"
|
||||||
|
echo " ╚══════════════════════════════════════╝"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
self_update
|
||||||
|
update_miyagi
|
||||||
|
|
||||||
|
update_dep "checkzfs" "$CHECKZFS_URL" "/usr/local/bin/checkzfs"
|
||||||
|
update_dep "check-snapshot-age" "$CHECK_SNAPSHOT_AGE_URL" "/usr/local/bin/check-snapshot-age"
|
||||||
|
update_dep "cleansnaps" "$CLEANSNAPS_URL" "/usr/local/bin/cleansnaps"
|
||||||
|
update_dep "disk_smart_info" "$DISK_SMART_INFO_URL" "/usr/lib/check_mk_agent/plugins/disk_smart_info"
|
||||||
|
|
||||||
|
print_status
|
||||||
|
ok "Update abgeschlossen."
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_args "$@"
|
||||||
|
main
|
||||||
Reference in new issue
Block a user