Fehler in der Oberflaeche abfangen, Backups planbar machen
Der Anlass: "Backup erstellen" bei fehlendem Container beendete die
ganze TUI mit einer Fehlerzeile in der Shell.
Ursachen waren zwei, beide behoben:
1. die() in GUI-Pfaden. Neue Helfer gui_need_container/gui_need_sites
melden das Problem im Dialog und kehren zurueck. Interaktives wie
Shell und Terminal-Browser laeuft jetzt ueber gui_run_interactive
in einer Subshell mit Weiter-mit-ENTER.
2. "set -e". Schon ein Rueckgabewert != 0 aus einer Menuefunktion
beendete das Skript, weil Menuezweige keine Bedingung sind. 47
"|| return" auf "|| return 0" gestellt und 37 Menuezweige mit
"|| true" abgesichert. Ausserdem schlug ein "clear" ohne TERM fehl
und riss alles mit - drei Aufrufe abgesichert.
Jeder Hauptmenuepunkt wurde einzeln durchlaufen und kehrt sauber zurueck.
Neu: Backup-Jobs
Der Menuepunkt heisst jetzt "Backup erstellen / planen" mit Untermenue
(manuell erstellen, Jobs verwalten, Automatik ein/aus, Zeitplan
anzeigen, Job sofort ausfuehren). Dieselben Jobs liegen auch in den
Einstellungen unter "Backup-Jobs".
Manuelle Backups nehmen weiterhin immer BACKUP_DIR aus der .env.
Jeder Job hat dagegen sein eigenes Zielverzeichnis, seinen eigenen
Zeitplan, eigene Optionen und eine eigene Aufbewahrung, nach der er
sein Zielverzeichnis selbst aufraeumt.
Vollstaendig auch per Parameter:
job list | status | add | set | del | enable | disable
| run | run-all | auto [on|off]
mit --name --sites --cron --dir --keep --no-rrds --no-logs --stop
--disabled.
"job auto on" erzeugt aus den aktiven Jobs /etc/cron.d/checkmk-backup,
eine Zeile je Job mit dessen eigenem Zeitplan. Ohne root werden die
Zeilen ausgegeben statt kommentarlos zu scheitern. Der Schalter steht
als BACKUP_AUTO in der .env, die Jobs in backup-jobs.conf.
Nebenbei behoben: "local f; f=... tmp" fuehrte tmp als Kommando aus,
wodurch job_put und job_remove nichts schrieben.
Dokumentiert als Abschnitt 15.1 in beiden Sprachfassungen.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+686
-72
@@ -89,6 +89,21 @@ KOMMANDOS - Backup / Restore / Migration
|
||||
|
||||
prune --keep N nur die N neuesten Backups behalten
|
||||
|
||||
job list angelegte Backup-Jobs anzeigen
|
||||
job status Zeitplan, Cron-Datei und Schalter anzeigen
|
||||
job add --name N --cron "15 2 * * *" [Optionen] Job anlegen
|
||||
--sites ALL|a,b zu sichernde Sites (Vorgabe ALL)
|
||||
--dir VERZ Zielverzeichnis des Jobs (Vorgabe: $BACKUP_DIR)
|
||||
--keep N Anzahl Backups, die im Ziel bleiben (0 = alle)
|
||||
--no-rrds --no-logs --stop wie bei "backup"
|
||||
--disabled angelegt, aber noch nicht eingeplant
|
||||
job set NAME [Optionen] vorhandenen Job aendern
|
||||
job del NAME Job loeschen
|
||||
job enable|disable NAME Job ein-/ausschalten
|
||||
job run NAME Job sofort ausfuehren
|
||||
job run-all alle aktiven Jobs ausfuehren
|
||||
job auto [on|off] automatische Ausfuehrung per cron ein/aus
|
||||
|
||||
KOMMANDOS - Checkmk-Image beschaffen
|
||||
image status konfiguriertes und lokal vorhandene Images anzeigen
|
||||
image list lokal vorhandene Checkmk-Images
|
||||
@@ -1217,6 +1232,334 @@ EOF
|
||||
LAST_BACKUP_FILE="$outfile"
|
||||
}
|
||||
|
||||
# =====================================================================
|
||||
# Backup-Jobs (geplante Backups)
|
||||
#
|
||||
# Manuelle Backups nehmen immer BACKUP_DIR aus der .env. Geplante Jobs
|
||||
# bringen ihr eigenes Zielverzeichnis mit - so kann z.B. taeglich auf
|
||||
# eine NAS-Freigabe und woechentlich woanders hin gesichert werden.
|
||||
#
|
||||
# Ablage: backup-jobs.conf im Projektverzeichnis, eine Zeile je Job:
|
||||
# name|sites|cron|verzeichnis|optionen|aufbewahren|aktiv
|
||||
# Ausgefuehrt werden sie ueber /etc/cron.d/checkmk-backup, das aus
|
||||
# dieser Datei erzeugt wird ("job auto on").
|
||||
# =====================================================================
|
||||
|
||||
JOBS_FILE_NAME="backup-jobs.conf"
|
||||
CRON_FILE="/etc/cron.d/checkmk-backup"
|
||||
|
||||
jobs_file() { printf '%s/%s\n' "$PROJECT_DIR" "$JOBS_FILE_NAME"; }
|
||||
|
||||
jobs_init() {
|
||||
local f; f="$(jobs_file)"
|
||||
[ -f "$f" ] && return 0
|
||||
cat >"$f" <<'EOF'
|
||||
# Backup-Jobs fuer cmk-manage.sh - eine Zeile je Job:
|
||||
# name|sites|cron|verzeichnis|optionen|aufbewahren|aktiv
|
||||
#
|
||||
# name nur Buchstaben, Ziffern, _ und -
|
||||
# sites ALL oder Site-Namen durch Komma getrennt
|
||||
# cron fuenf Cron-Felder, z.B. "15 2 * * *"
|
||||
# verzeichnis Zielverzeichnis (absolut oder relativ zum Projekt)
|
||||
# optionen leer oder --no-rrds / --no-logs / --stop (mit Leerzeichen)
|
||||
# aufbewahren Anzahl der Backups, die im Zielverzeichnis bleiben (0 = alle)
|
||||
# aktiv on oder off
|
||||
#
|
||||
# Bearbeiten moeglichst ueber: cmk-manage.sh job ... bzw. das Menue.
|
||||
EOF
|
||||
ok "Neue Jobdatei angelegt: $f"
|
||||
}
|
||||
|
||||
jobs_read() { # nur Datenzeilen
|
||||
local f; f="$(jobs_file)"
|
||||
[ -f "$f" ] || return 0
|
||||
grep -vE '^[[:space:]]*(#|$)' "$f" || true
|
||||
}
|
||||
|
||||
job_line() { jobs_read | awk -F'|' -v n="$1" '$1==n {print; exit}'; }
|
||||
job_exists() { [ -n "$(job_line "$1")" ]; }
|
||||
job_f() { printf '%s' "$1" | cut -d'|' -f"$2"; }
|
||||
|
||||
job_dir_abs() { # Verzeichnis eines Jobs absolut
|
||||
local d="$1"
|
||||
case "$d" in /*) printf '%s\n' "$d" ;; *) printf '%s\n' "$PROJECT_DIR/${d#./}" ;; esac
|
||||
}
|
||||
|
||||
job_validate_name() {
|
||||
case "$1" in
|
||||
''|*[!A-Za-z0-9_-]*) echo "Der Name darf nur Buchstaben, Ziffern, _ und - enthalten."; return 1 ;;
|
||||
esac
|
||||
return 0
|
||||
}
|
||||
|
||||
job_validate_cron() {
|
||||
local n; n="$(printf '%s' "$1" | awk '{print NF}')"
|
||||
[ "$n" = 5 ] || { echo "Ein Cron-Ausdruck besteht aus genau fuenf Feldern, z.B. '15 2 * * *'."; return 1; }
|
||||
return 0
|
||||
}
|
||||
|
||||
job_validate_field() { # keine Trennzeichen in Feldern
|
||||
case "$1" in *'|'*) echo "Das Zeichen | ist in diesem Feld nicht erlaubt."; return 1 ;; esac
|
||||
return 0
|
||||
}
|
||||
|
||||
# Job schreiben (anlegen oder ersetzen)
|
||||
job_put() { # name sites cron dir opts keep enabled
|
||||
jobs_init
|
||||
local f tmp; f="$(jobs_file)"
|
||||
tmp="$(mktemp)"
|
||||
awk -F'|' -v n="$1" '$1!=n' "$f" >"$tmp"
|
||||
printf '%s|%s|%s|%s|%s|%s|%s\n' "$1" "$2" "$3" "$4" "$5" "$6" "$7" >>"$tmp"
|
||||
# Kommentarkopf erhalten
|
||||
{ grep -E '^[[:space:]]*#' "$f" 2>/dev/null || true; grep -vE '^[[:space:]]*(#|$)' "$tmp" ; } >"$f"
|
||||
rm -f "$tmp"
|
||||
}
|
||||
|
||||
job_remove() {
|
||||
local f tmp; f="$(jobs_file)"
|
||||
[ -f "$f" ] || return 0
|
||||
tmp="$(mktemp)"
|
||||
awk -F'|' -v n="$1" '$1!=n' "$f" >"$tmp" && mv "$tmp" "$f"
|
||||
}
|
||||
|
||||
# --- Aufraeumen im Zielverzeichnis eines Jobs -------------------------
|
||||
prune_in_dir() { # verzeichnis anzahl
|
||||
local dir="$1" keep="$2" i=0
|
||||
[ -n "$keep" ] && [ "$keep" -gt 0 ] 2>/dev/null || return 0
|
||||
local -a files=()
|
||||
mapfile -t files < <(find "$dir" -maxdepth 1 -type f -name '*.tar.gz' -printf '%T@ %p\n' 2>/dev/null \
|
||||
| sort -rn | cut -d' ' -f2-)
|
||||
[ ${#files[@]} -le "$keep" ] && return 0
|
||||
for ((i=keep; i<${#files[@]}; i++)); do
|
||||
log "Aufbewahrung: entferne $(basename "${files[$i]}")"
|
||||
rm -f "${files[$i]}"
|
||||
done
|
||||
}
|
||||
|
||||
# --- Job ausfuehren ---------------------------------------------------
|
||||
job_run_one() {
|
||||
local name="$1" line
|
||||
line="$(job_line "$name")"
|
||||
[ -n "$line" ] || die "Job '$name' ist nicht vorhanden. Uebersicht: $SELF job list"
|
||||
|
||||
local sites cron dir opts keep enabled
|
||||
sites="$(job_f "$line" 2)"; cron="$(job_f "$line" 3)"; dir="$(job_f "$line" 4)"
|
||||
opts="$(job_f "$line" 5)"; keep="$(job_f "$line" 6)"; enabled="$(job_f "$line" 7)"
|
||||
|
||||
dir="$(job_dir_abs "$dir")"
|
||||
mkdir -p "$dir" || die "Zielverzeichnis nicht anlegbar: $dir"
|
||||
|
||||
log "Job '$name' - Ziel $dir, Sites ${sites}${opts:+, Optionen $opts}"
|
||||
require_cmk_running
|
||||
|
||||
local -a args=(--dir "$dir" --label "$name")
|
||||
local o
|
||||
for o in $opts; do
|
||||
case "$o" in
|
||||
--no-rrds|--no-logs|--stop) args+=("$o") ;;
|
||||
*) warn "Unbekannte Option '$o' im Job '$name' - wird uebergangen." ;;
|
||||
esac
|
||||
done
|
||||
if [ "$sites" = ALL ]; then
|
||||
args+=(--all)
|
||||
else
|
||||
local sname
|
||||
for sname in $(printf '%s' "$sites" | tr ',' ' '); do args+=(--site "$sname"); done
|
||||
fi
|
||||
|
||||
ASSUME_YES=1 cmd_backup "${args[@]}"
|
||||
prune_in_dir "$dir" "$keep"
|
||||
ok "Job '$name' abgeschlossen."
|
||||
}
|
||||
|
||||
# --- Cron ------------------------------------------------------------
|
||||
cron_write() {
|
||||
jobs_init
|
||||
local n=0 line name cron
|
||||
local tmp; tmp="$(mktemp)"
|
||||
{
|
||||
printf '# Automatische Checkmk-Backups - erzeugt von cmk-manage.sh\n'
|
||||
printf '# Nicht von Hand aendern, Quelle ist %s\n' "$(jobs_file)"
|
||||
printf 'SHELL=/bin/sh\n'
|
||||
printf 'PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin\n\n'
|
||||
while IFS= read -r line; do
|
||||
[ -n "$line" ] || continue
|
||||
[ "$(job_f "$line" 7)" = on ] || continue
|
||||
name="$(job_f "$line" 1)"; cron="$(job_f "$line" 3)"
|
||||
printf '%s root %s -y job run %s >>/var/log/cmk-backup.log 2>&1\n' \
|
||||
"$cron" "$SELF" "$name"
|
||||
n=$((n+1))
|
||||
done < <(jobs_read)
|
||||
} >"$tmp"
|
||||
|
||||
if [ "$n" -eq 0 ]; then
|
||||
rm -f "$tmp"
|
||||
warn "Kein aktiver Job vorhanden - es wird nichts eingeplant."
|
||||
[ -f "$CRON_FILE" ] && { rm -f "$CRON_FILE"; log "Vorhandene Cron-Datei entfernt."; }
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
err "Zum Schreiben von $CRON_FILE werden root-Rechte benoetigt."
|
||||
echo
|
||||
cat "$tmp"
|
||||
echo
|
||||
log "Die Zeilen oben von Hand nach $CRON_FILE uebernehmen, oder erneut mit sudo aufrufen."
|
||||
rm -f "$tmp"
|
||||
return 1
|
||||
fi
|
||||
install -m 0644 "$tmp" "$CRON_FILE"
|
||||
rm -f "$tmp"
|
||||
ok "$n Job(s) eingeplant in $CRON_FILE"
|
||||
}
|
||||
|
||||
cron_remove_file() {
|
||||
if [ -f "$CRON_FILE" ]; then
|
||||
[ "$(id -u)" -eq 0 ] || die "Zum Entfernen von $CRON_FILE werden root-Rechte benoetigt."
|
||||
rm -f "$CRON_FILE"
|
||||
ok "Automatische Backups abgeschaltet ($CRON_FILE entfernt)."
|
||||
else
|
||||
ok "Es war nichts eingeplant."
|
||||
fi
|
||||
}
|
||||
|
||||
backup_auto_enabled() {
|
||||
case "$(printf '%s' "${BACKUP_AUTO:-off}" | tr 'A-Z' 'a-z')" in
|
||||
on|true|1|yes|ja) return 0 ;; *) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# --- Anzeige ----------------------------------------------------------
|
||||
jobs_list_table() {
|
||||
printf '%-14s %-12s %-14s %-28s %-18s %5s %s\n' \
|
||||
"NAME" "SITES" "ZEITPLAN" "ZIEL" "OPTIONEN" "HALT" "AKTIV"
|
||||
local line n=0
|
||||
while IFS= read -r line; do
|
||||
[ -n "$line" ] || continue
|
||||
printf '%-14s %-12s %-14s %-28s %-18s %5s %s\n' \
|
||||
"$(job_f "$line" 1)" "$(job_f "$line" 2)" "$(job_f "$line" 3)" \
|
||||
"$(job_f "$line" 4)" "$(job_f "$line" 5)" "$(job_f "$line" 6)" "$(job_f "$line" 7)"
|
||||
n=$((n+1))
|
||||
done < <(jobs_read)
|
||||
[ "$n" -eq 0 ] && echo "(noch keine Jobs angelegt)"
|
||||
return 0
|
||||
}
|
||||
|
||||
cmd_job() {
|
||||
local sub="${1:-list}"; [ $# -gt 0 ] && shift || true
|
||||
case "$sub" in
|
||||
list|ls) jobs_list_table ;;
|
||||
|
||||
status)
|
||||
printf '\n%sAutomatische Backups%s\n' "$C_BLD" "$C_RST"
|
||||
printf ' Schalter : %s\n' "$(backup_auto_enabled && echo 'ein (BACKUP_AUTO=on)' || echo 'aus (BACKUP_AUTO=off)')"
|
||||
printf ' Cron-Datei : %s\n' "$([ -f "$CRON_FILE" ] && echo "$CRON_FILE" || echo 'nicht vorhanden')"
|
||||
printf ' Jobdatei : %s\n' "$(jobs_file)"
|
||||
printf ' Manuell nach: %s (BACKUP_DIR)\n' "$BACKUP_DIR"
|
||||
printf '\n%sJobs%s\n' "$C_BLD" "$C_RST"
|
||||
jobs_list_table
|
||||
if [ -f "$CRON_FILE" ]; then
|
||||
printf '\n%sEingeplant%s\n' "$C_BLD" "$C_RST"
|
||||
grep -vE '^[[:space:]]*(#|SHELL|PATH|$)' "$CRON_FILE" | sed 's/^/ /'
|
||||
fi
|
||||
echo ;;
|
||||
|
||||
add|set)
|
||||
local name="" sites="ALL" cron="" dir="" keep="7" enabled="on" opts=""
|
||||
local is_set=""; [ "$sub" = set ] && is_set=1
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--name) name="$2"; shift 2 ;;
|
||||
--sites) sites="$2"; shift 2 ;;
|
||||
--cron) cron="$2"; shift 2 ;;
|
||||
--dir) dir="$2"; shift 2 ;;
|
||||
--keep) keep="$2"; shift 2 ;;
|
||||
--no-rrds) opts="$opts --no-rrds"; shift ;;
|
||||
--no-logs) opts="$opts --no-logs"; shift ;;
|
||||
--stop) opts="$opts --stop"; shift ;;
|
||||
--enabled) enabled=on; shift ;;
|
||||
--disabled) enabled=off; shift ;;
|
||||
*) [ -z "$name" ] && { name="$1"; shift; } || die "Unbekannte Option fuer 'job $sub': $1" ;;
|
||||
esac
|
||||
done
|
||||
[ -n "$name" ] || die "--name fehlt."
|
||||
local msg
|
||||
msg="$(job_validate_name "$name")" || die "$msg"
|
||||
|
||||
local old=""; old="$(job_line "$name")"
|
||||
if [ -n "$is_set" ]; then
|
||||
[ -n "$old" ] || die "Job '$name' ist nicht vorhanden."
|
||||
# nicht angegebene Felder aus dem Bestand uebernehmen
|
||||
[ "$sites" = ALL ] && sites="$(job_f "$old" 2)"
|
||||
[ -z "$cron" ] && cron="$(job_f "$old" 3)"
|
||||
[ -z "$dir" ] && dir="$(job_f "$old" 4)"
|
||||
[ -z "$opts" ] && opts="$(job_f "$old" 5)"
|
||||
[ "$keep" = 7 ] && keep="$(job_f "$old" 6)"
|
||||
enabled="$(job_f "$old" 7)"
|
||||
else
|
||||
[ -z "$old" ] || die "Job '$name' existiert bereits. Aendern mit: $SELF job set $name ..."
|
||||
fi
|
||||
dir="${dir:-$BACKUP_DIR}"
|
||||
[ -n "$cron" ] || die "--cron fehlt, z.B. --cron '15 2 * * *'."
|
||||
msg="$(job_validate_cron "$cron")" || die "$msg"
|
||||
msg="$(job_validate_field "$dir")" || die "$msg"
|
||||
case "$keep" in ''|*[!0-9]*) die "--keep braucht eine Zahl (0 = alles behalten)." ;; esac
|
||||
|
||||
opts="$(printf '%s' "$opts" | sed 's/^ *//')"
|
||||
job_put "$name" "$sites" "$cron" "$dir" "$opts" "$keep" "$enabled"
|
||||
ok "Job '$name' gespeichert."
|
||||
jobs_list_table | sed -n "1p;/^$name /p"
|
||||
backup_auto_enabled && cron_write || log "Einplanen mit: $SELF job auto on"
|
||||
;;
|
||||
|
||||
del|rm|delete)
|
||||
[ $# -ge 1 ] || die "Name fehlt: $SELF job del NAME"
|
||||
job_exists "$1" || die "Job '$1' ist nicht vorhanden."
|
||||
confirm "Job '$1' wirklich loeschen?" || die "Abgebrochen."
|
||||
job_remove "$1"; ok "Job '$1' geloescht."
|
||||
backup_auto_enabled && cron_write || true
|
||||
;;
|
||||
|
||||
enable|disable)
|
||||
[ $# -ge 1 ] || die "Name fehlt: $SELF job $sub NAME"
|
||||
local l; l="$(job_line "$1")"
|
||||
[ -n "$l" ] || die "Job '$1' ist nicht vorhanden."
|
||||
local st=on; [ "$sub" = disable ] && st=off
|
||||
job_put "$1" "$(job_f "$l" 2)" "$(job_f "$l" 3)" "$(job_f "$l" 4)" \
|
||||
"$(job_f "$l" 5)" "$(job_f "$l" 6)" "$st"
|
||||
ok "Job '$1' ist jetzt $st."
|
||||
backup_auto_enabled && cron_write || true
|
||||
;;
|
||||
|
||||
run)
|
||||
[ $# -ge 1 ] || die "Name fehlt: $SELF job run NAME"
|
||||
job_run_one "$1" ;;
|
||||
|
||||
run-all)
|
||||
local line n=0
|
||||
while IFS= read -r line; do
|
||||
[ -n "$line" ] || continue
|
||||
[ "$(job_f "$line" 7)" = on ] || continue
|
||||
job_run_one "$(job_f "$line" 1)" || warn "Job fehlgeschlagen: $(job_f "$line" 1)"
|
||||
n=$((n+1))
|
||||
done < <(jobs_read)
|
||||
[ "$n" -eq 0 ] && warn "Kein aktiver Job vorhanden."
|
||||
return 0 ;;
|
||||
|
||||
auto)
|
||||
case "${1:-}" in
|
||||
on) env_set BACKUP_AUTO on; BACKUP_AUTO=on; cron_write ;;
|
||||
off) env_set BACKUP_AUTO off; BACKUP_AUTO=off; cron_remove_file ;;
|
||||
'') printf ' Automatische Backups: %s\n' \
|
||||
"$(backup_auto_enabled && echo ein || echo aus)" ;;
|
||||
*) die "Aufruf: $SELF job auto [on|off]" ;;
|
||||
esac ;;
|
||||
|
||||
*) die "Unbekanntes Unterkommando 'job $sub'.
|
||||
Moeglich: list | status | add | set | del | enable | disable | run | run-all | auto" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# =====================================================================
|
||||
# Auflisten / Aufraeumen
|
||||
# =====================================================================
|
||||
@@ -1807,7 +2150,8 @@ browser|BROWSER_TOOLS_IMAGE|text|Werkzeug-Image (leer = automatisch)||1
|
||||
paths|CMK_DATA_DIR|path|Checkmk-Sites (Bind-Mount)||
|
||||
paths|NPM_DATA_DIR|path|Proxy-Manager-Daten||
|
||||
paths|NPM_LE_DIR|path|Let's-Encrypt-Zertifikate||
|
||||
paths|BACKUP_DIR|path|Backups und Bundles||
|
||||
paths|BACKUP_DIR|path|Backups und Bundles (manuell)||
|
||||
backup|BACKUP_AUTO|choice|Automatische Backups per cron|off:on|
|
||||
paths|IMAGE_DIR|path|Heruntergeladene Image-Tarballs||
|
||||
cert|CERT_DOMAIN|text|FQDN fuer selbstsignierte Zertifikate||
|
||||
cert|CERT_DAYS|int|Gueltigkeit in Tagen||
|
||||
@@ -1825,6 +2169,7 @@ npm|NGINX Proxy Manager
|
||||
browser|Terminal-Browser
|
||||
paths|Verzeichnisse
|
||||
cert|Selbstsignierte Zertifikate
|
||||
backup|Backup-Automatik
|
||||
EOF
|
||||
}
|
||||
|
||||
@@ -1893,6 +2238,8 @@ settings_post_set() {
|
||||
NPM_ENABLED)
|
||||
# Container entsprechend entfernen bzw. starten
|
||||
cmd_npm_enable "$val" ;;
|
||||
BACKUP_AUTO)
|
||||
cmd_job auto "$val" ;;
|
||||
CMK_IMAGE|CMK_SITE_ID|CMK_CONTAINER_NAME|NPM_IMAGE|NPM_CONTAINER_NAME|TZ|CMK_LIVESTATUS_TCP|NPM_DISABLE_IPV6|CMK_DATA_DIR|NPM_DATA_DIR|NPM_LE_DIR)
|
||||
log "Wirksam nach: $SELF up (Container werden neu erstellt)" ;;
|
||||
esac
|
||||
@@ -1934,6 +2281,8 @@ cmd_config() {
|
||||
cmd_npm_port "$val"
|
||||
elif [ "$key" = NPM_ENABLED ]; then
|
||||
cmd_npm_enable "$val"
|
||||
elif [ "$key" = BACKUP_AUTO ]; then
|
||||
env_set "$key" "$val"; BACKUP_AUTO="$val"; cmd_job auto "$val"
|
||||
else
|
||||
env_set "$key" "$val" "$opt"
|
||||
ok "$key=$val"
|
||||
@@ -2157,7 +2506,61 @@ EOF
|
||||
# =====================================================================
|
||||
# ncurses-Oberflaeche
|
||||
# =====================================================================
|
||||
# ---------------------------------------------------------------------
|
||||
# GUI-sichere Vorbedingungen
|
||||
#
|
||||
# In der Oberflaeche darf nichts "die" aufrufen - das wuerde die ganze TUI
|
||||
# beenden. Diese Helfer melden das Problem im Dialog und geben 1 zurueck.
|
||||
# ---------------------------------------------------------------------
|
||||
gui_need_container() {
|
||||
if ! container_exists "$CMK_CONTAINER_NAME"; then
|
||||
ui_msg "Checkmk-Container fehlt" \
|
||||
"Der Container '$CMK_CONTAINER_NAME' existiert nicht.
|
||||
|
||||
Dafuer wird er zuerst gebraucht. Im Hauptmenue:
|
||||
stack -> Stack starten
|
||||
|
||||
Auf der Kommandozeile:
|
||||
$SELF up"
|
||||
return 1
|
||||
fi
|
||||
if ! container_running "$CMK_CONTAINER_NAME"; then
|
||||
ui_msg "Checkmk-Container gestoppt" \
|
||||
"Der Container '$CMK_CONTAINER_NAME' existiert, laeuft aber nicht.
|
||||
|
||||
Im Hauptmenue: stack -> Stack starten
|
||||
Kommandozeile: $SELF up"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
gui_need_sites() {
|
||||
gui_need_container || return 1
|
||||
local n; n="$(cmk_sites | sed '/^$/d' | wc -l)"
|
||||
if [ "$n" -eq 0 ]; then
|
||||
ui_msg "Keine Sites" \
|
||||
"Im Container ist noch keine Site vorhanden.
|
||||
|
||||
Der Container legt die Site aus CMK_SITE_ID beim ersten Start selbst an.
|
||||
Alternativ eine Site importieren: Hauptmenue -> import"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# Interaktives Kommando ausfuehren, ohne dass ein Fehler die TUI beendet
|
||||
gui_run_interactive() {
|
||||
clear 2>/dev/null || true
|
||||
if ! ( "$@" ); then
|
||||
printf '\n%sDas Kommando wurde mit einem Fehler beendet.%s\n' "$C_YEL" "$C_RST"
|
||||
fi
|
||||
printf '\nWeiter mit ENTER ...'
|
||||
read -r _ </dev/tty || true
|
||||
}
|
||||
|
||||
gui_pick_site() { # -> Site auf stdout
|
||||
gui_need_container || return 1
|
||||
local -a items=() s
|
||||
while IFS= read -r s; do
|
||||
[ -n "$s" ] || continue
|
||||
@@ -2220,7 +2623,7 @@ gui_stack_menu() {
|
||||
}
|
||||
|
||||
gui_backup() {
|
||||
require_cmk_running
|
||||
gui_need_sites || return 0
|
||||
local -a items=() s
|
||||
while IFS= read -r s; do
|
||||
[ -n "$s" ] || continue
|
||||
@@ -2229,14 +2632,14 @@ gui_backup() {
|
||||
[ ${#items[@]} -gt 0 ] || { ui_msg "Backup" "Keine Sites vorhanden."; return; }
|
||||
|
||||
local chosen
|
||||
chosen="$(ui_checklist "Backup" "Zu sichernde Site(s) mit LEERTASTE markieren:" "${items[@]}")" || return
|
||||
chosen="$(ui_checklist "Backup" "Zu sichernde Site(s) mit LEERTASTE markieren:" "${items[@]}")" || return 0
|
||||
[ -n "$chosen" ] || { ui_msg "Backup" "Keine Site ausgewaehlt."; return; }
|
||||
|
||||
local optsel
|
||||
optsel="$(ui_checklist "Backup-Optionen" "Optionen waehlen:" \
|
||||
no-rrds "Performance-Daten (RRD) auslassen - kleineres Archiv" off \
|
||||
no-logs "Logdateien auslassen" off \
|
||||
stop "Site waehrend des Backups stoppen (konsistenter)" off)" || return
|
||||
stop "Site waehrend des Backups stoppen (konsistenter)" off)" || return 0
|
||||
|
||||
local label
|
||||
label="$(ui_input "Kennzeichnung" "Optionaler Text fuer den Dateinamen (leer = keiner):" "")" || label=""
|
||||
@@ -2255,10 +2658,217 @@ gui_backup() {
|
||||
ui_run "Backup laeuft" bash -c "cd '$PROJECT_DIR' && '$SELF' -y ${args[*]}"
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Backup: erstellen und planen
|
||||
# ---------------------------------------------------------------------
|
||||
gui_backup_menu() {
|
||||
while :; do
|
||||
local auto sel
|
||||
auto="$(backup_auto_enabled && echo 'ein' || echo 'aus')"
|
||||
sel="$(ui_menu "Backup erstellen / planen" \
|
||||
"Manuelle Backups gehen immer nach:
|
||||
$BACKUP_DIR (Einstellung BACKUP_DIR)
|
||||
|
||||
Geplante Jobs haben ihr eigenes Zielverzeichnis.
|
||||
Automatische Ausfuehrung: $auto" \
|
||||
manuell "Backup jetzt erstellen" \
|
||||
jobs "Backup-Jobs verwalten (anlegen/aendern/loeschen)" \
|
||||
auto "Automatische Ausfuehrung ein/aus (derzeit: $auto)" \
|
||||
status "Zeitplan und Jobs anzeigen" \
|
||||
jetzt "Einen Job sofort ausfuehren" \
|
||||
back "zurueck")" || return 0
|
||||
case "$sel" in
|
||||
manuell) gui_backup || true ;;
|
||||
jobs) gui_jobs_menu || true ;;
|
||||
auto) gui_backup_auto || true ;;
|
||||
status) local f; f="$(mktemp)"; NO_COLOR=1 cmd_job status >"$f" 2>&1 || true
|
||||
ui_text "Backup-Zeitplan" "$f"; rm -f "$f" ;;
|
||||
jetzt) gui_job_run_now || true ;;
|
||||
back) return 0 ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
gui_backup_auto() {
|
||||
if backup_auto_enabled; then
|
||||
ui_yesno "Automatische Backups" \
|
||||
"Automatische Backups sind eingeschaltet.
|
||||
|
||||
Abschalten? Die Jobs bleiben erhalten, es wird nur
|
||||
nichts mehr automatisch ausgefuehrt." || return 0
|
||||
ui_run "Automatik abschalten" bash -c "cd '$PROJECT_DIR' && '$SELF' -y job auto off"
|
||||
else
|
||||
local n; n="$(jobs_read | awk -F'|' '$7=="on"' | wc -l)"
|
||||
if [ "$n" -eq 0 ]; then
|
||||
ui_msg "Keine aktiven Jobs" \
|
||||
"Es ist noch kein aktiver Backup-Job angelegt.
|
||||
|
||||
Zuerst unter 'Backup-Jobs verwalten' einen Job anlegen -
|
||||
dort wird auch der Zeitplan festgelegt."
|
||||
return
|
||||
fi
|
||||
ui_yesno "Automatische Backups" \
|
||||
"$n aktive(r) Job(s) werden in die System-Cron eingetragen
|
||||
($CRON_FILE).
|
||||
|
||||
Dafuer werden root-Rechte benoetigt. Einschalten?" || return 0
|
||||
ui_run "Automatik einschalten" bash -c "cd '$PROJECT_DIR' && '$SELF' -y job auto on"
|
||||
fi
|
||||
load_env "${ENV_FILE:-$PROJECT_DIR/.env}"
|
||||
}
|
||||
|
||||
gui_pick_job() { # -> Jobname auf stdout
|
||||
local -a items=() line
|
||||
while IFS= read -r line; do
|
||||
[ -n "$line" ] || continue
|
||||
items+=("$(job_f "$line" 1)" \
|
||||
"$(job_f "$line" 3) -> $(job_f "$line" 4) [$(job_f "$line" 7)]")
|
||||
done < <(jobs_read)
|
||||
if [ ${#items[@]} -eq 0 ]; then
|
||||
ui_msg "Keine Jobs" "Es ist noch kein Backup-Job angelegt."
|
||||
return 1
|
||||
fi
|
||||
ui_menu "Job waehlen" "Vorhandene Backup-Jobs:" "${items[@]}"
|
||||
}
|
||||
|
||||
gui_job_run_now() {
|
||||
gui_need_sites || return 0
|
||||
local j; j="$(gui_pick_job)" || return 0
|
||||
[ -n "$j" ] || return 0
|
||||
ui_yesno "Job ausfuehren" "Job '$j' jetzt ausfuehren?" || return 0
|
||||
ui_run "Job '$j'" bash -c "cd '$PROJECT_DIR' && '$SELF' -y job run '$j'"
|
||||
}
|
||||
|
||||
gui_jobs_menu() {
|
||||
while :; do
|
||||
local sel
|
||||
sel="$(ui_menu "Backup-Jobs" \
|
||||
"Jeder Job hat eigenen Zeitplan, eigenes Zielverzeichnis
|
||||
und eigene Aufbewahrung.
|
||||
|
||||
Jobdatei: $(jobs_file)" \
|
||||
list "Jobs anzeigen" \
|
||||
neu "Neuen Job anlegen" \
|
||||
edit "Job aendern" \
|
||||
toggle "Job ein-/ausschalten" \
|
||||
del "Job loeschen" \
|
||||
back "zurueck")" || return 0
|
||||
case "$sel" in
|
||||
list) local f; f="$(mktemp)"; NO_COLOR=1 jobs_list_table >"$f" 2>&1 || true
|
||||
ui_text "Backup-Jobs" "$f"; rm -f "$f" ;;
|
||||
neu) gui_job_edit "" || true ;;
|
||||
edit) local j; j="$(gui_pick_job)" || continue; [ -n "$j" ] && gui_job_edit "$j" ;;
|
||||
toggle) local j2 l st
|
||||
j2="$(gui_pick_job)" || continue; [ -n "$j2" ] || continue
|
||||
l="$(job_line "$j2")"; st=disable
|
||||
[ "$(job_f "$l" 7)" = off ] && st=enable
|
||||
ui_run "Job $st" bash -c "cd '$PROJECT_DIR' && '$SELF' -y job $st '$j2'" ;;
|
||||
del) local j3; j3="$(gui_pick_job)" || continue; [ -n "$j3" ] || continue
|
||||
ui_yesno "Loeschen" "Job '$j3' wirklich loeschen?\n\n(Bereits erstellte Backups bleiben erhalten.)" \
|
||||
&& ui_run "Job loeschen" bash -c "cd '$PROJECT_DIR' && '$SELF' -y job del '$j3'" ;;
|
||||
back) return 0 ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# Zeitplan bequem zusammenklicken
|
||||
gui_pick_cron() { # vorgabe -> cron-ausdruck auf stdout
|
||||
local cur="${1:-15 2 * * *}" kind time hh mm dow dom
|
||||
kind="$(ui_menu "Zeitplan" "Wie oft soll gesichert werden?" \
|
||||
taeglich "jeden Tag" \
|
||||
woechentlich "einmal pro Woche" \
|
||||
monatlich "einmal pro Monat" \
|
||||
frei "Cron-Ausdruck selbst eingeben")" || return 1
|
||||
if [ "$kind" = frei ]; then
|
||||
ui_input "Cron-Ausdruck" "Fuenf Felder: Minute Stunde Tag Monat Wochentag" "$cur"
|
||||
return
|
||||
fi
|
||||
time="$(ui_input "Uhrzeit" "Uhrzeit im Format HH:MM" "02:15")" || return 1
|
||||
case "$time" in
|
||||
[0-9][0-9]:[0-9][0-9]) : ;;
|
||||
*) ui_msg "Ungueltig" "Bitte im Format HH:MM angeben, z.B. 02:15."; return 1 ;;
|
||||
esac
|
||||
hh="${time%%:*}"; mm="${time##*:}"
|
||||
hh="$((10#$hh))"; mm="$((10#$mm))"
|
||||
[ "$hh" -le 23 ] && [ "$mm" -le 59 ] || { ui_msg "Ungueltig" "Stunde 0-23, Minute 0-59."; return 1; }
|
||||
case "$kind" in
|
||||
taeglich) printf '%s %s * * *\n' "$mm" "$hh" ;;
|
||||
woechentlich) dow="$(ui_menu "Wochentag" "An welchem Tag?" \
|
||||
1 Montag 2 Dienstag 3 Mittwoch 4 Donnerstag \
|
||||
5 Freitag 6 Samstag 0 Sonntag)" || return 1
|
||||
printf '%s %s * * %s\n' "$mm" "$hh" "$dow" ;;
|
||||
monatlich) dom="$(ui_input "Tag im Monat" "Welcher Tag (1-28)?" "1")" || return 1
|
||||
case "$dom" in ''|*[!0-9]*) ui_msg "Ungueltig" "Bitte eine Zahl."; return 1 ;; esac
|
||||
printf '%s %s %s * *\n' "$mm" "$hh" "$dom" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
gui_job_edit() { # name (leer = neu)
|
||||
local name="$1" line="" sites="ALL" cron="15 2 * * *" dir="$BACKUP_DIR" opts="" keep="7"
|
||||
if [ -n "$name" ]; then
|
||||
line="$(job_line "$name")"
|
||||
sites="$(job_f "$line" 2)"; cron="$(job_f "$line" 3)"; dir="$(job_f "$line" 4)"
|
||||
opts="$(job_f "$line" 5)"; keep="$(job_f "$line" 6)"
|
||||
else
|
||||
name="$(ui_input "Neuer Job" "Name des Jobs (Buchstaben, Ziffern, _ und -):" "nachts")" || return 0
|
||||
local msg
|
||||
if ! msg="$(job_validate_name "$name")"; then ui_msg "Ungueltiger Name" "$msg"; return; fi
|
||||
if job_exists "$name"; then ui_msg "Schon vorhanden" "Ein Job namens '$name' existiert bereits."; return; fi
|
||||
fi
|
||||
|
||||
# Sites auswaehlen
|
||||
if gui_need_sites; then
|
||||
local -a items=() sname
|
||||
items+=("ALL" "alle Sites (auch spaeter neu angelegte)" "$([ "$sites" = ALL ] && echo on || echo off)")
|
||||
while IFS= read -r sname; do
|
||||
[ -n "$sname" ] || continue
|
||||
items+=("$sname" "einzelne Site" \
|
||||
"$(printf '%s' ",$sites," | grep -q ",$sname," && echo on || echo off)")
|
||||
done < <(cmk_sites)
|
||||
local chosen
|
||||
chosen="$(ui_checklist "Sites" "Was soll dieser Job sichern?\n(ALL schliesst alle anderen ein)" "${items[@]}")" || return 0
|
||||
chosen="$(printf '%s' "$chosen" | tr -d '"')"
|
||||
[ -n "$chosen" ] || { ui_msg "Keine Auswahl" "Es wurde keine Site gewaehlt."; return; }
|
||||
case " $chosen " in
|
||||
*" ALL "*) sites=ALL ;;
|
||||
*) sites="$(printf '%s' "$chosen" | tr ' ' ',')" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
cron="$(gui_pick_cron "$cron")" || return 0
|
||||
[ -n "$cron" ] || return 0
|
||||
|
||||
dir="$(ui_input "Zielverzeichnis" \
|
||||
"Wohin soll dieser Job sichern?
|
||||
(absolut oder relativ zum Projekt; wird bei Bedarf angelegt)" "$dir")" || return 0
|
||||
[ -n "$dir" ] || return 0
|
||||
|
||||
keep="$(ui_input "Aufbewahrung" \
|
||||
"Wie viele Backups sollen in diesem Verzeichnis bleiben?
|
||||
0 = alle behalten" "$keep")" || return 0
|
||||
case "$keep" in ''|*[!0-9]*) ui_msg "Ungueltig" "Bitte eine Zahl angeben."; return ;; esac
|
||||
|
||||
local optsel
|
||||
optsel="$(ui_checklist "Optionen" "Optionen fuer diesen Job:" \
|
||||
no-rrds "Performance-Daten (RRD) auslassen" "$(case "$opts" in *no-rrds*) echo on ;; *) echo off ;; esac)" \
|
||||
no-logs "Logdateien auslassen" "$(case "$opts" in *no-logs*) echo on ;; *) echo off ;; esac)" \
|
||||
stop "Site waehrend des Backups stoppen" "$(case "$opts" in *stop*) echo on ;; *) echo off ;; esac)")" || return 0
|
||||
opts=""
|
||||
case "$optsel" in *no-rrds*) opts="$opts --no-rrds" ;; esac
|
||||
case "$optsel" in *no-logs*) opts="$opts --no-logs" ;; esac
|
||||
case "$optsel" in *stop*) opts="$opts --stop" ;; esac
|
||||
opts="$(printf '%s' "$opts" | sed 's/^ *//')"
|
||||
|
||||
local action=add; job_exists "$name" && action=set
|
||||
ui_run "Job speichern" bash -c \
|
||||
"cd '$PROJECT_DIR' && '$SELF' -y job $action --name '$name' --sites '$sites' \
|
||||
--cron '$cron' --dir '$dir' --keep '$keep' $opts"
|
||||
}
|
||||
|
||||
gui_restore() {
|
||||
require_cmk_running
|
||||
local file; file="$(gui_pick_backup)" || return
|
||||
[ -n "$file" ] || return
|
||||
gui_need_container || return 0
|
||||
local file; file="$(gui_pick_backup)" || return 0
|
||||
[ -n "$file" ] || return 0
|
||||
|
||||
local f; f="$(mktemp)"
|
||||
bundle_show "$file" >"$f" 2>&1 || true
|
||||
@@ -2267,15 +2877,15 @@ gui_restore() {
|
||||
bundle_read "$file" || { ui_msg "Fehler" "Diese Datei ist kein Checkmk-Backup."; return; }
|
||||
local reuse=""
|
||||
if cmk_site_exists "$B_SITE"; then
|
||||
ui_yesno "Site existiert" "Die Site '$B_SITE' ist bereits vorhanden.\n\nSoll sie UEBERSCHRIEBEN werden?\nAlle aktuellen Daten dieser Site gehen verloren!" || return
|
||||
ui_yesno "Site existiert" "Die Site '$B_SITE' ist bereits vorhanden.\n\nSoll sie UEBERSCHRIEBEN werden?\nAlle aktuellen Daten dieser Site gehen verloren!" || return 0
|
||||
reuse="--reuse --kill"
|
||||
fi
|
||||
ui_yesno "Restore starten" "Site '$B_SITE' aus\n$(basename "$file")\nwiederherstellen?" || return
|
||||
ui_yesno "Restore starten" "Site '$B_SITE' aus\n$(basename "$file")\nwiederherstellen?" || return 0
|
||||
ui_run "Restore laeuft" bash -c "cd '$PROJECT_DIR' && '$SELF' -y restore --file '$file' $reuse"
|
||||
}
|
||||
|
||||
gui_import() {
|
||||
require_cmk_running
|
||||
gui_need_container || return 0
|
||||
ui_msg "Site importieren" \
|
||||
"Import einer Site von einer Direktinstallation (Bare-Metal/VM).
|
||||
|
||||
@@ -2288,8 +2898,8 @@ Wichtig fuer die Agents:
|
||||
- Port 8000 (Agent-Receiver) ist erreichbar
|
||||
Dann muessen die Agents NICHT neu eingerichtet werden."
|
||||
|
||||
local file; file="$(gui_pick_backup)" || return
|
||||
[ -n "$file" ] || return
|
||||
local file; file="$(gui_pick_backup)" || return 0
|
||||
[ -n "$file" ] || return 0
|
||||
|
||||
local f; f="$(mktemp)"
|
||||
bundle_show "$file" >"$f" 2>&1 || true
|
||||
@@ -2298,7 +2908,7 @@ Dann muessen die Agents NICHT neu eingerichtet werden."
|
||||
bundle_read "$file" || { ui_msg "Fehler" "Diese Datei ist kein Migrations-Bundle."; return; }
|
||||
local reuse=""
|
||||
if cmk_site_exists "$B_SITE"; then
|
||||
ui_yesno "Site existiert" "Die Site '$B_SITE' existiert bereits im Container.\n\nUEBERSCHREIBEN?" || return
|
||||
ui_yesno "Site existiert" "Die Site '$B_SITE' existiert bereits im Container.\n\nUEBERSCHREIBEN?" || return 0
|
||||
reuse="--reuse --kill"
|
||||
fi
|
||||
local setdef=""
|
||||
@@ -2334,7 +2944,7 @@ gui_backups_menu() {
|
||||
}
|
||||
|
||||
gui_sites_menu() {
|
||||
require_cmk_running
|
||||
gui_need_container || return 0
|
||||
while :; do
|
||||
local sel
|
||||
sel="$(ui_menu "Sites" "Sites im Container '$CMK_CONTAINER_NAME'" \
|
||||
@@ -2371,14 +2981,14 @@ Edition/Version: ${CMK_EDITION:-raw} / ${CMK_VERSION:-?}" \
|
||||
case "$sel" in
|
||||
status) local f; f="$(mktemp)"; NO_COLOR=1 cmd_image status >"$f" 2>&1 || true
|
||||
ui_text "Image-Status" "$f"; rm -f "$f" ;;
|
||||
test) gui_image_test ;;
|
||||
pull) gui_image_pull ;;
|
||||
download) gui_image_download ;;
|
||||
test) gui_image_test || true ;;
|
||||
pull) gui_image_pull || true ;;
|
||||
download) gui_image_download || true ;;
|
||||
load) local lf; lf="$(ui_pick_file "${IMAGE_DIR:-$PROJECT_DIR/images}" '*.tar.gz')" || continue
|
||||
[ -n "$lf" ] || continue
|
||||
ui_run "Image einspielen" bash -c "cd '$PROJECT_DIR' && '$SELF' -y image load --file '$lf'"
|
||||
load_env "${ENV_FILE:-$PROJECT_DIR/.env}" ;;
|
||||
use) gui_image_use ;;
|
||||
use) gui_image_use || true ;;
|
||||
back) return 0 ;;
|
||||
esac
|
||||
done
|
||||
@@ -2398,14 +3008,14 @@ gui_image_pick_edition() {
|
||||
|
||||
gui_image_test() {
|
||||
local ed ver user pass
|
||||
ed="$(gui_image_pick_edition)" || return
|
||||
ver="$(ui_input "Version" "Version (fuer die Pruefung des Downloadportals):" "${CMK_VERSION:-}")" || return
|
||||
ed="$(gui_image_pick_edition)" || return 0
|
||||
ver="$(ui_input "Version" "Version (fuer die Pruefung des Downloadportals):" "${CMK_VERSION:-}")" || return 0
|
||||
local -a extra=()
|
||||
if ui_yesno "Zugangsdaten" "Zugangsdaten aus der .env verwenden?\n\nRegistry : ${CMK_REGISTRY_USER:-<leer>}\nDownload : ${CMK_DOWNLOAD_USER:-<leer>}\n\n<Nein> = jetzt eingeben"; then
|
||||
:
|
||||
else
|
||||
user="$(ui_input "Zugangsdaten" "Benutzer (Checkmk-Kundenportal):" "${CMK_REGISTRY_USER:-}")" || return
|
||||
pass="$(ui_password "Zugangsdaten" "Kennwort:")" || return
|
||||
user="$(ui_input "Zugangsdaten" "Benutzer (Checkmk-Kundenportal):" "${CMK_REGISTRY_USER:-}")" || return 0
|
||||
pass="$(ui_password "Zugangsdaten" "Kennwort:")" || return 0
|
||||
[ -n "$user" ] && extra+=(--user "$user" --password "$pass")
|
||||
fi
|
||||
ui_run "Zugangsdaten pruefen" bash -c \
|
||||
@@ -2414,13 +3024,13 @@ gui_image_test() {
|
||||
|
||||
gui_image_pull() {
|
||||
local ed ver user pass
|
||||
ed="$(gui_image_pick_edition)" || return
|
||||
ver="$(ui_input "Version" "Version bzw. Tag (z.B. 2.3.0p23 oder 2.3.0-latest):" "${CMK_VERSION:-}")" || return
|
||||
[ -n "$ver" ] || return
|
||||
ed="$(gui_image_pick_edition)" || return 0
|
||||
ver="$(ui_input "Version" "Version bzw. Tag (z.B. 2.3.0p23 oder 2.3.0-latest):" "${CMK_VERSION:-}")" || return 0
|
||||
[ -n "$ver" ] || return 0
|
||||
local -a extra=()
|
||||
if [ "$ed" = enterprise ] || [ -n "${CMK_REGISTRY_USER:-}" ]; then
|
||||
user="$(ui_input "Registry-Anmeldung" "Benutzer (Checkmk-Kundenportal):" "${CMK_REGISTRY_USER:-}")" || return
|
||||
pass="$(ui_password "Registry-Anmeldung" "Kennwort:")" || return
|
||||
user="$(ui_input "Registry-Anmeldung" "Benutzer (Checkmk-Kundenportal):" "${CMK_REGISTRY_USER:-}")" || return 0
|
||||
pass="$(ui_password "Registry-Anmeldung" "Kennwort:")" || return 0
|
||||
[ -n "$user" ] && extra+=(--user "$user" --password "$pass")
|
||||
fi
|
||||
ui_run "Image holen" bash -c "cd '$PROJECT_DIR' && '$SELF' -y image pull --edition '$ed' --version '$ver' ${extra[*]+${extra[*]}}"
|
||||
@@ -2429,11 +3039,11 @@ gui_image_pull() {
|
||||
|
||||
gui_image_download() {
|
||||
local ed ver user pass
|
||||
ed="$(gui_image_pick_edition)" || return
|
||||
ver="$(ui_input "Version" "EXAKTE Version (z.B. 2.3.0p23 - kein '-latest'):" "${CMK_VERSION:-}")" || return
|
||||
[ -n "$ver" ] || return
|
||||
user="$(ui_input "Downloadportal" "Benutzer:" "${CMK_DOWNLOAD_USER:-}")" || return
|
||||
pass="$(ui_password "Downloadportal" "Kennwort:")" || return
|
||||
ed="$(gui_image_pick_edition)" || return 0
|
||||
ver="$(ui_input "Version" "EXAKTE Version (z.B. 2.3.0p23 - kein '-latest'):" "${CMK_VERSION:-}")" || return 0
|
||||
[ -n "$ver" ] || return 0
|
||||
user="$(ui_input "Downloadportal" "Benutzer:" "${CMK_DOWNLOAD_USER:-}")" || return 0
|
||||
pass="$(ui_password "Downloadportal" "Kennwort:")" || return 0
|
||||
ui_run "Image herunterladen" bash -c "cd '$PROJECT_DIR' && '$SELF' -y image download --edition '$ed' --version '$ver' --user '$user' --password '$pass'"
|
||||
load_env "${ENV_FILE:-$PROJECT_DIR/.env}"
|
||||
}
|
||||
@@ -2446,7 +3056,7 @@ gui_image_use() {
|
||||
done < <(image_local_list)
|
||||
[ ${#items[@]} -gt 0 ] || { ui_msg "Images" "Es ist kein Checkmk-Image lokal vorhanden.\n\nZuerst 'pull', 'download' oder 'load' verwenden."; return; }
|
||||
local sel
|
||||
sel="$(ui_menu "Image auswaehlen" "Lokal vorhandene Checkmk-Images:" "${items[@]}")" || return
|
||||
sel="$(ui_menu "Image auswaehlen" "Lokal vorhandene Checkmk-Images:" "${items[@]}")" || return 0
|
||||
ui_run "Image setzen" bash -c "cd '$PROJECT_DIR' && '$SELF' -y image use '$sel'"
|
||||
load_env "${ENV_FILE:-$PROJECT_DIR/.env}"
|
||||
}
|
||||
@@ -2485,15 +3095,15 @@ gui_settings_edit() {
|
||||
IFS=':'
|
||||
done
|
||||
IFS="$IFS_BAK"
|
||||
new="$(ui_radiolist "$key" "$label\n\nAktuell: ${cur:-<leer>}" "${ropts[@]}")" || return
|
||||
new="$(ui_radiolist "$key" "$label\n\nAktuell: ${cur:-<leer>}" "${ropts[@]}")" || return 0
|
||||
[ "$new" = auto ] && new=""
|
||||
;;
|
||||
password)
|
||||
new="$(ui_password "$key" "$label\n\n(leer lassen = unveraendert)")" || return
|
||||
new="$(ui_password "$key" "$label\n\n(leer lassen = unveraendert)")" || return 0
|
||||
[ -z "$new" ] && return
|
||||
;;
|
||||
*)
|
||||
new="$(ui_input "$key" "$label\n\nTyp: $typ$([ -n "$opt" ] && echo ' (darf leer bleiben)')" "$cur")" || return
|
||||
new="$(ui_input "$key" "$label\n\nTyp: $typ$([ -n "$opt" ] && echo ' (darf leer bleiben)')" "$cur")" || return 0
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -2541,6 +3151,7 @@ gui_settings_menu() {
|
||||
while IFS='|' read -r c l; do
|
||||
[ -n "$c" ] && items+=("$c" "$l")
|
||||
done < <(settings_categories)
|
||||
items+=("jobs" "Backup-Jobs (Zeitplan, Zielpfade, Aufbewahrung)")
|
||||
items+=("show" "Alle Werte auflisten")
|
||||
items+=("editor" "Datei .env im Editor oeffnen")
|
||||
items+=("back" "zurueck")
|
||||
@@ -2550,12 +3161,14 @@ gui_settings_menu() {
|
||||
Datei: ${ENV_FILE:-$PROJECT_DIR/.env}" "${items[@]}")" || return 0
|
||||
case "$sel" in
|
||||
back) return 0 ;;
|
||||
jobs) gui_jobs_menu || true ;;
|
||||
show) local f; f="$(mktemp)"
|
||||
{ printf '%-24s %-10s %s\n' "SCHLUESSEL" "BEREICH" "WERT"
|
||||
NO_COLOR=1 cmd_config list; } >"$f" 2>&1
|
||||
ui_text "Alle Einstellungen" "$f"; rm -f "$f" ;;
|
||||
editor) local ef="${ENV_FILE:-$PROJECT_DIR/.env}"
|
||||
clear; "${EDITOR:-nano}" "$ef"
|
||||
if [ ! -f "$ef" ]; then ui_msg "Keine .env" "Die Datei $ef existiert nicht.\n\nAnlegen mit: cp .env.example .env"; continue; fi
|
||||
clear 2>/dev/null || true; "${EDITOR:-nano}" "$ef"
|
||||
load_env "$ef"; ui_msg "Konfiguration" "Die .env wurde neu eingelesen." ;;
|
||||
*) local title
|
||||
title="$(settings_categories | awk -F'|' -v c="$sel" '$1==c{print $2}')"
|
||||
@@ -2588,17 +3201,16 @@ Oberflaeche des Proxy Managers darstellen." \
|
||||
[ -n "$u" ] && NPM_ADMIN_URL="$u" ;;
|
||||
build) ui_run "Werkzeug-Image bauen" bash -c "cd '$PROJECT_DIR' && '$SELF' browser --build-only" || true ;;
|
||||
back) return 0 ;;
|
||||
*) clear
|
||||
cmd_browser --engine "$sel" --url "${NPM_ADMIN_URL:-http://127.0.0.1:81}" || true
|
||||
;;
|
||||
*) gui_run_interactive cmd_browser --engine "$sel" \
|
||||
--url "${NPM_ADMIN_URL:-http://127.0.0.1:81}" ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
gui_cert() {
|
||||
local domain alt days
|
||||
domain="$(ui_input "Zertifikat" "FQDN / Common Name:" "${CERT_DOMAIN:-checkmk.example.local}")" || return
|
||||
[ -n "$domain" ] || return
|
||||
domain="$(ui_input "Zertifikat" "FQDN / Common Name:" "${CERT_DOMAIN:-checkmk.example.local}")" || return 0
|
||||
[ -n "$domain" ] || return 0
|
||||
alt="$(ui_input "Zertifikat" "Weitere Namen/IPs (durch Leerzeichen getrennt, optional):" "$(primary_ip)")" || alt=""
|
||||
days="$(ui_input "Zertifikat" "Gueltigkeit in Tagen:" "${CERT_DAYS:-3650}")" || days=3650
|
||||
local -a a=(); local x
|
||||
@@ -2616,7 +3228,7 @@ Runtime : $RUNTIME Standard-Site: $CMK_SITE_ID
|
||||
Backups : $BACKUP_DIR" \
|
||||
status "Status von Containern und Sites" \
|
||||
stack "Stack steuern (Start/Stop/Logs/Update)" \
|
||||
backup "Backup erstellen" \
|
||||
backup "Backup erstellen / planen" \
|
||||
restore "Backup wiederherstellen" \
|
||||
import "Site von Direktinstallation importieren" \
|
||||
manage "Backups verwalten (Liste/Details/Loeschen)" \
|
||||
@@ -2628,22 +3240,23 @@ Backups : $BACKUP_DIR" \
|
||||
shell "Root-Shell im Checkmk-Container" \
|
||||
quit "Beenden")" || break
|
||||
case "$sel" in
|
||||
status) gui_status ;;
|
||||
stack) gui_stack_menu ;;
|
||||
backup) gui_backup ;;
|
||||
restore) gui_restore ;;
|
||||
import) gui_import ;;
|
||||
manage) gui_backups_menu ;;
|
||||
sites) gui_sites_menu ;;
|
||||
image) gui_image_menu ;;
|
||||
browser) gui_browser_menu ;;
|
||||
cert) gui_cert ;;
|
||||
config) gui_settings_menu ;;
|
||||
shell) clear; cmd_shell || true ;;
|
||||
status) gui_status || true ;;
|
||||
stack) gui_stack_menu || true ;;
|
||||
backup) gui_backup_menu || true ;;
|
||||
restore) gui_restore || true ;;
|
||||
import) gui_import || true ;;
|
||||
manage) gui_backups_menu || true ;;
|
||||
sites) gui_sites_menu || true ;;
|
||||
image) gui_image_menu || true ;;
|
||||
browser) gui_browser_menu || true ;;
|
||||
cert) gui_cert || true ;;
|
||||
config) gui_settings_menu || true ;;
|
||||
shell) gui_need_container || continue
|
||||
gui_run_interactive cmd_shell ;;
|
||||
quit) break ;;
|
||||
esac
|
||||
done
|
||||
clear
|
||||
clear 2>/dev/null || true
|
||||
ok "Beendet."
|
||||
}
|
||||
|
||||
@@ -2670,29 +3283,30 @@ main() {
|
||||
gui|menu) gui_main ;;
|
||||
up|start) cmd_up ;;
|
||||
down|stop) cmd_down ;;
|
||||
restart) cmd_restart ;;
|
||||
pull) cmd_pull ;;
|
||||
status) cmd_status ;;
|
||||
logs) cmd_logs "$@" ;;
|
||||
shell) cmd_shell ;;
|
||||
omd) cmd_omd "$@" ;;
|
||||
sites) cmd_sites ;;
|
||||
restart) cmd_restart || true ;;
|
||||
pull) cmd_pull || true ;;
|
||||
status) cmd_status || true ;;
|
||||
logs) cmd_logs "$@" || true ;;
|
||||
shell) cmd_shell || true ;;
|
||||
omd) cmd_omd "$@" || true ;;
|
||||
sites) cmd_sites || true ;;
|
||||
site-start) cmd_site_start "$@" ;;
|
||||
site-stop) cmd_site_stop "$@" ;;
|
||||
start-all-sites) cmd_start_all_sites ;;
|
||||
backup) cmd_backup "$@" ;;
|
||||
list) cmd_list ;;
|
||||
prune) cmd_prune "$@" ;;
|
||||
backup) cmd_backup "$@" || true ;;
|
||||
list) cmd_list || true ;;
|
||||
prune) cmd_prune "$@" || true ;;
|
||||
job|jobs) cmd_job "$@" ;;
|
||||
verify) local vf=""; [ "${1:-}" = "--file" ] && vf="$2"; [ -n "$vf" ] || vf="${1:-}"
|
||||
[ -n "$vf" ] || die "--file fehlt."; bundle_verify "$vf" ;;
|
||||
restore) cmd_restore "$@" ;;
|
||||
import) cmd_import "$@" ;;
|
||||
cert) cmd_cert "$@" ;;
|
||||
image) cmd_image "$@" ;;
|
||||
browser) cmd_browser "$@" ;;
|
||||
restore) cmd_restore "$@" || true ;;
|
||||
import) cmd_import "$@" || true ;;
|
||||
cert) cmd_cert "$@" || true ;;
|
||||
image) cmd_image "$@" || true ;;
|
||||
browser) cmd_browser "$@" || true ;;
|
||||
npm-port) cmd_npm_port "$@" ;;
|
||||
npm-enable) cmd_npm_enable "$@" ;;
|
||||
config) cmd_config "$@" ;;
|
||||
config) cmd_config "$@" || true ;;
|
||||
help|-h|--help) usage ;;
|
||||
*) err "Unbekanntes Kommando: $cmd"; echo; usage; exit 1 ;;
|
||||
esac
|
||||
|
||||
@@ -44,6 +44,7 @@ load_env() {
|
||||
CMK_SITE_ID="${CMK_SITE_ID:-cmk}"
|
||||
CMK_IMAGE="${CMK_IMAGE:-docker.io/checkmk/check-mk-raw:2.3.0-latest}"
|
||||
NPM_ENABLED="${NPM_ENABLED:-on}"
|
||||
BACKUP_AUTO="${BACKUP_AUTO:-off}"
|
||||
NPM_ADMIN_PORT="${NPM_ADMIN_PORT:-81}"
|
||||
# Leer = automatisch aus dem Admin-Port ableiten
|
||||
NPM_ADMIN_URL="${NPM_ADMIN_URL:-http://127.0.0.1:$NPM_ADMIN_PORT}"
|
||||
|
||||
Reference in New Issue
Block a user