Thomas Stallinger 8615d9fde1 Konsole: kompakte Kreisel/Haken-Anzeige statt Log-Wand + Kernel-Zeitstempel entfernt
Nutzer-Feedback (01.09.2026, echter Hardware-Test) mit mehreren
zusammenhaengenden Konsolen-UX-Punkten:

- "Die Darstellung des Abarbeitens der Skripte und Module ist noch nicht
  schön... Modul XY läuft (kreiselnde Symbole)... gründer Haken als
  erledigt" - neue run_module_quiet() (utils.sh) fuehrt ein Modul im
  Hintergrund aus, zeigt waehrenddessen einen Kreisel auf derselben Zeile,
  am Ende [OK] (gruen) oder [FEHLER] (rot) + volle mitgeschnittene Ausgabe
  bei einem Fehlschlag. Nur im echten Auto-Modus aktiv (dort fragt kein
  Modul interaktiv nach) - 40_backend.sh bleibt bewusst verbose
  (TUXFLOTTE_VERBOSE_MODULES), da dort der neue Download-Fortschrittsbalken
  sichtbar bleiben soll.
- "Bei Entpacken und schreiben des Archivs, kann man das einen
  Fortschrittsbalken... anzeigen lassen?" - curl "--silent" durch
  "--progress-bar" ersetzt (image_deploy.sh).
- "Der Kernel Zeitstempel ist für den Kunden nicht interessant, sondern
  nur verwirrend." - eigentliche Ursache war nicht der GRUB-Splash
  (separater Commit), sondern StandardOutput=journal+console im
  systemd-Unit: journald spiegelt Konsolenausgaben im kmsg-Stil mit
  monotonem "[  12.345678]"-Zeitstempel, sah aus wie ein Kernel-Log.
  Jetzt "StandardOutput/Error=console" (direkt an /dev/tty1, kein
  journald) - journalctl zeigt dadurch nur noch Dienst-Lebenszyklus-
  Meldungen, die volle Ausgabe bleibt vollstaendig in
  /var/log/tuxflotte-installer.log (bereits der dokumentierte Weg).

Zwei echte Bugs beim eigenen Boot-Test dieser Aenderung gefunden+behoben:
(1) log_module_title() gab den Titel per Command-Substitution zurueck -
lief dadurch in einer Subshell, der TUXFLOTTE_STEP_COUNT-Zaehler blieb
immer bei 1 stehen ("[1/12]" bei jedem Modul). Jetzt ueber eine globale
TUXFLOTTE_CURRENT_TITLE-Variable statt Command-Substitution.
(2) Unicode-Kreisel (⠋⠙...) und Haken (✓/✗) wurden von der
vt-Konsolenschriftart nicht abgedeckt, zeigten nur einen generischen
Ersatz-Kasten - auf reines ASCII (|/-\, "[OK]"/"[FEHLER]") umgestellt,
garantiert auf jeder Konsolenschriftart lesbar.

Ausserdem: Beep + "Stick jetzt entfernen"-Hinweis + ENTER-Bestaetigung
(oder automatischer Neustart nach 5 Minuten) direkt vor dem finalen
Reboot in backend.sh (separater Commit, siehe backend_postinstall()).

Live in QEMU boot-getestet (Zaehler/Farben/Kreisel im Rohlog verifiziert,
kompletter Auto-Modus-Durchlauf inkl. Fehlerfall-Dump getestet, voller
End-to-End-Durchlauf bis zum echten Mint-Cinnamon-Login-Bildschirm nach
Reboot bestaetigt).
2026-09-01 15:46:18 +02:00

131 lines
4.0 KiB
Bash

#!/usr/bin/env bash
load_config() {
local config_file="$1"
if [[ -f "$config_file" ]]; then
# shellcheck disable=SC1090
source "$config_file"
log_info "Konfiguration geladen: $config_file"
else
log_warn "Keine Konfiguration gefunden: $config_file"
fi
}
# Module, die auch im Auto-Modus verbose bleiben (keine Kreisel/Haken-
# Kompaktdarstellung, siehe run_module_quiet()): 40_backend.sh ist der mit
# Abstand langlaeufigste Schritt (Minuten statt Sekunden, Golden-Image-
# Download+Extraktion) - hier bleibt die eigene Schritt-fuer-Schritt-
# Ausgabe (Partitionieren/Formatieren/... + der Download-Fortschrittsbalken,
# siehe image_deploy_extract_image_from_url()) sichtbar, statt hinter einem
# einzelnen Kreisel zu verschwinden.
declare -a TUXFLOTTE_VERBOSE_MODULES=(40_backend.sh)
_tuxflotte_module_is_verbose() {
local module_name="$1"
local candidate
for candidate in "${TUXFLOTTE_VERBOSE_MODULES[@]}"; do
[[ "${candidate}" == "${module_name}" ]] && return 0
done
return 1
}
# Kompakte Modul-Ausfuehrung fuer den unbeaufsichtigten Auto-Modus (siehe
# log_module_title()/log_module_ok()/log_module_failed() in logging.sh):
# Modul laeuft im Hintergrund, waehrenddessen ein Kreisel auf derselben
# Zeile, am Ende entweder ein gruener Haken (Erfolg, Detailausgabe nur ins
# Logfile) oder ein rotes Kreuz + die volle mitgeschnittene Ausgabe auf der
# Konsole (Fehlschlag - Fehlersuche darf nie schlechter werden als vorher).
run_module_quiet() {
local module="$1"
local module_name
module_name="$(basename "${module}")"
log_module_title "${module_name}"
local title="${TUXFLOTTE_CURRENT_TITLE}"
local output_file
output_file="$(mktemp)"
# shellcheck disable=SC1090
"${module}" >"${output_file}" 2>&1 &
local pid=$!
if _tuxflotte_console_is_live; then
printf '%s ' "${title}"
local frame_index=0
local frame_count="${#_TUXFLOTTE_SPINNER_FRAMES[@]}"
while kill -0 "${pid}" 2>/dev/null; do
printf '\r%s %s' "${title}" "${_TUXFLOTTE_SPINNER_FRAMES[$((frame_index % frame_count))]}"
frame_index=$((frame_index + 1))
sleep 0.1
done
fi
# "wait || status=$?" statt eines nackten "wait"-Aufrufs - genau das
# bekannte &&/||-Gegenstueck zu "set -e" (siehe die mount-Bind-Lehre in
# image_deploy.sh), hier bewusst genutzt, um den echten Exit-Code sauber
# auszuwerten statt das ganze Skript sofort abzubrechen.
local status=0
wait "${pid}" || status=$?
if [[ "${status}" -eq 0 ]]; then
log_module_ok "${title}"
else
log_module_failed "${title}"
echo
cat "${output_file}"
echo
fi
[[ -n "${TUXFLOTTE_LOG_FILE:-}" ]] && cat "${output_file}" >>"${TUXFLOTTE_LOG_FILE}" 2>/dev/null
rm -f "${output_file}"
return "${status}"
}
run_module() {
local module="$1"
local mode="${2:-normal}"
local module_name
module_name="$(basename "$module")"
[[ -f "$module" ]] || error_exit "Modul nicht gefunden: $module"
if [[ "${DRY_RUN:-false}" == true && "$mode" != "always" ]]; then
log_step "${module_name}"
log_warn "Dry-Run: Modul übersprungen: $module"
return 0
fi
# Kompakte Kreisel/Haken-Darstellung nur im echten Auto-Modus: nur dort
# ist sichergestellt, dass kein Modul interaktiv nach Eingaben fragt
# (12_enrollment_auth.sh/20_profile_selection.sh/25_installation_confirm.sh
# pruefen TUXFLOTTE_AUTO_MODE selbst und ueberspringen ihre Prompts) -
# ein Prompt-Text waere sonst zusammen mit der restlichen Ausgabe in
# output_file gefangen und fuer die Person vor dem Geraet unsichtbar.
if [[ "${TUXFLOTTE_AUTO_MODE:-false}" == "true" ]] && ! _tuxflotte_module_is_verbose "${module_name}"; then
run_module_quiet "$module"
return "$?"
fi
log_step "${module_name}"
log_info "Starte Modul: ${module_name}"
# shellcheck disable=SC1090
"$module"
log_success "Modul abgeschlossen: ${module_name}"
}
require_root() {
[[ "$EUID" -eq 0 ]] || error_exit "Installer muss als root ausgeführt werden."
}
command_exists() {
command -v "$1" >/dev/null 2>&1
}