197 lines
8.2 KiB
Bash
197 lines
8.2 KiB
Bash
#!/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"
|
||
HOOKS_DIR_POST_UPDATE="${CONFIG_DIR}/hooks.d/post-update"
|
||
HOOKS_DIR_POST_BACKUP="${CONFIG_DIR}/hooks.d/post-backup"
|
||
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-Verzeichnisse sicherstellen
|
||
mkdir -p "$HOOKS_DIR" "$HOOKS_DIR_POST_UPDATE" "$HOOKS_DIR_POST_BACKUP"
|
||
|
||
# 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"
|
||
|
||
# Standard-Hooks (ehemals fest im Skript, seit dieser Version als Hook
|
||
# ausgelagert) einmalig anlegen, damit bestehende Installationen ihr
|
||
# bisheriges Verhalten behalten. Bereits vorhandene Dateien (ggf. vom
|
||
# User angepasst/deaktiviert) werden nicht überschrieben.
|
||
if [[ ! -e "${HOOKS_DIR_POST_UPDATE}/10-disable-pve-notifications.sh" ]]; then
|
||
curl -fsSL "${base}/hooks.d/post-update/10-disable-pve-notifications.sh" \
|
||
-o "${HOOKS_DIR_POST_UPDATE}/10-disable-pve-notifications.sh" 2>/dev/null \
|
||
&& chmod +x "${HOOKS_DIR_POST_UPDATE}/10-disable-pve-notifications.sh" \
|
||
&& info "Hook 10-disable-pve-notifications.sh neu angelegt (aktiv)" \
|
||
|| warn "Hook 10-disable-pve-notifications.sh konnte nicht angelegt werden"
|
||
fi
|
||
if [[ ! -e "${HOOKS_DIR_POST_BACKUP}/10-pbs-log-clear.sh" ]]; then
|
||
curl -fsSL "${base}/hooks.d/post-backup/10-pbs-log-clear.sh" \
|
||
-o "${HOOKS_DIR_POST_BACKUP}/10-pbs-log-clear.sh" 2>/dev/null \
|
||
&& chmod +x "${HOOKS_DIR_POST_BACKUP}/10-pbs-log-clear.sh" \
|
||
&& info "Hook 10-pbs-log-clear.sh neu angelegt (aktiv)" \
|
||
|| warn "Hook 10-pbs-log-clear.sh konnte nicht angelegt werden"
|
||
fi
|
||
if [[ ! -e "${HOOKS_DIR_POST_BACKUP}/20-pve-log-clear.sh" ]]; then
|
||
curl -fsSL "${base}/hooks.d/post-backup/20-pve-log-clear.sh" \
|
||
-o "${HOOKS_DIR_POST_BACKUP}/20-pve-log-clear.sh" 2>/dev/null \
|
||
&& chmod +x "${HOOKS_DIR_POST_BACKUP}/20-pve-log-clear.sh" \
|
||
&& info "Hook 20-pve-log-clear.sh neu angelegt (aktiv)" \
|
||
|| warn "Hook 20-pve-log-clear.sh konnte nicht angelegt werden"
|
||
fi
|
||
|
||
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
|