fix: noninteractive verworfen, automatic-ubiquity+Autoklicker, drei echte Bugs behoben

- noninteractive-Frontend endgueltig verworfen: PageNoninteractive-Stubs
  fuehren strukturell zur Endlosschleife im choose_partition-Zustands-
  automaten von ubi-partman.py, unabhaengig vom Preseed-Stand.
- Umstieg auf automatic-ubiquity (echte GTK-Oberflaeche) + eigener
  Autoklicker (live-updates/opt/tuxflotte/scripts/autoclicker.sh +
  systemd-Service), ausgeloest per Boot-Keyword tuxflotte-autoclick.
- Bug 1: jq fehlte beim echten Kiosk-Auslauf (kein manueller Vorab-
  Installationsschritt wie in Testlaeufen) - neues Modul
  00_preflight.sh installiert es als allererstes.
- Bug 2: echter Ubiquity-Crash in ubi-prepare.py (TypeError: Argument 1
  does not allow None as a value) - gezielter Sed-Patch im bestehenden
  99casperboot-Hook.
- Bug 3: 'd-i partman/choose_partition select finish' zwang denselben
  Endlosschleifen-Zustandsautomaten wie bei noninteractive, auch im
  GTK-Modus - Zeile ersatzlos entfernt, partman-auto/method+recipe
  genuegen.
- autoclicker.sh: Fenstersuche nach 'ubiquity' korrigiert (Fenstertitel
  ist tatsaechlich 'Installation (as superuser)', enthaelt das Wort nie).
- Alle vier Fixes live per QEMU verifiziert (jeweils frische Disk, realer
  Kiosk-Ausloeser/kexec-Pfad, nicht nur manuelle Nachstellung).

Offen: automatisierter Klick auf 'Jetzt installieren' auf der
Partitionierungs-Uebersichtsseite noch nicht zuverlaessig (Enter trifft
dort einen Ausklapp-Pfeil statt den Button). Siehe ADR-0023-Nachtrag.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Thomas Stallinger 2026-08-29 15:16:41 +02:00
parent 6087243c82
commit 941a58535d
7 changed files with 316 additions and 14 deletions

View File

@ -155,6 +155,7 @@ _tuxflotte_render_partman_recipe() {
local percent local percent
local size_mb local size_mb
local esp_mb=0 local esp_mb=0
local bios_grub_mb=0
scheme="$(jq --raw-output '.scheme // "single"' <<<"${partitioning_json}")" scheme="$(jq --raw-output '.scheme // "single"' <<<"${partitioning_json}")"
@ -178,6 +179,24 @@ _tuxflotte_render_partman_recipe() {
esp_mb=512 esp_mb=512
disk_size_mb="$(( disk_size_mb - esp_mb ))" disk_size_mb="$(( disk_size_mb - esp_mb ))"
recipe_body="${esp_mb} ${esp_mb} ${esp_mb} fat32 \$reusemethod{ } \$primary{ } method{ efi } format{ } . " recipe_body="${esp_mb} ${esp_mb} ${esp_mb} fat32 \$reusemethod{ } \$primary{ } method{ efi } format{ } . "
else
# Analoges Pendant fuer reinen BIOS-Betrieb: partman legt den
# Datentraeger auch ohne EFI offenbar als GPT an (real beim Testen
# bestaetigt: freier Speicher vor Partition 1 und nach der letzten
# Partition ist die GPT-Kopfdaten-Signatur, kein MSDOS-Layout). GPT +
# BIOS-Boot braucht eine kleine unformatierte Boot-Partition fuer den
# GRUB-Core, sonst schlaegt /usr/lib/partman/check.d/08biosgrub fehl
# und partman-partitioning/no_bootable_biosgrub sorgt fuer eine
# Endlosschleife zurueck ins choose_partition-Menue statt
# abzuschliessen (real beim Testen entdeckt und via 08biosgrub-
# Quelltext auf dem Live-Medium verifiziert - "true" bei dieser Frage
# bedeutet dort "Problem besteht weiterhin", nicht "trotzdem
# fortfahren", anders als bei den meisten uebrigen Boolean-Fragen in
# diesem Rezept). "$iflabel{ gpt }" macht die Stanza auf einem
# MSDOS-Datentraeger automatisch wirkungslos.
bios_grub_mb=1
disk_size_mb="$(( disk_size_mb - bios_grub_mb ))"
recipe_body="${bios_grub_mb} ${bios_grub_mb} ${bios_grub_mb} free \$iflabel{ gpt } \$reusemethod{ } method{ biosgrub } . "
fi fi
case "${scheme}" in case "${scheme}" in
@ -363,21 +382,32 @@ backend_launch() {
backend_log "Lade Kexec-Ziel fuer automatisierten Ubiquity-Start." backend_log "Lade Kexec-Ziel fuer automatisierten Ubiquity-Start."
# "noninteractive" (eigenes Boot-Keyword, siehe /usr/share/ubiquity/ # Ubiquitys eigenes "noninteractive"-Frontend (ubiquity/frontend/
# start-ubiquity-dm) laesst casper statt der GTK-Oberflaeche (ubiquity-dm # noninteractive.py, ueber das gleichnamige Boot-Keyword ausgewaehlt)
# -> gtk_ui.py) direkt "ubiquity noninteractive" aufrufen - Ubiquitys # arbeitet zwar rein ueber Debconf ohne je ein Fenster zu zeichnen, aber
# eigenes, mitgeliefertes Headless-Frontend (ubiquity/frontend/ # dessen Seite fuer die gefuehrte Partitionierung (ubi-partman.py) haengt
# noninteractive.py). Das arbeitet jede Seite mit auto_process=True rein # sich bei einem vollstaendig vorbefuellten Rezept in einer echten
# ueber Debconf ab, ohne jemals ein Fenster zu zeichnen oder einen Klick # Endlosschleife auf (staendiges Neuaufbauen des choose_partition-Menues,
# zu erwarten - der Unterschied zu "automatic-ubiquity" alleine: jenes # "partman/confirm" wird nie erreicht - real ueber >800 Wiederholungen
# startet weiterhin die GTK-Oberflaeche und fuellt dort nur die Werte # ohne Fortschritt bestaetigt, siehe ADR-0023-Nachtrag). Ursache: die
# vor, wartet aber pro Seite trotzdem auf "Continue" (real verifiziert, # PageNoninteractive-Klasse liefert fuer etliche vom GTK-Codepfad
# siehe ADR-0023-Nachtrag). "automatic-ubiquity" bleibt zusaetzlich # benoetigte Rueckfragen (get_autopartition_choice(), get_crypto_keys())
# gesetzt, weil start-ubiquity-dm bei einem GTK/X-Absturz automatisch # nur "pass"/None statt echter Werte.
# darauf als Fallback in den Noninteractive-Modus zurueckfaellt. #
# Deshalb bewusst zurueck auf "automatic-ubiquity" (echte GTK-Oberflaeche,
# PageGtk-Klasse - der von Ubiquity selbst getestete, produktiv genutzte
# Codepfad, auch fuer die Partitionierung). Der GTK-Assistent fuellt jede
# Seite aus dem Preseed vor, wartet aber weiterhin auf einen "Weiter"-Klick
# pro Seite (real verifiziert, siehe ADR-0023-Nachtrag) - dafuer laeuft
# zusaetzlich autoclicker.sh (live-updates/opt/tuxflotte/scripts/), per
# systemd-Service und ausgeloest durch das eigene Boot-Keyword
# "tuxflotte-autoclick" (harmlos bei jedem anderen Boot ohne dieses
# Keyword). "debug-ubiquity" (setzt debug="-d") macht
# /var/log/installer/debug ausfuehrlicher, hilfreich bei weiterer
# Fehlersuche.
kexec -l "${cdrom_vmlinuz}" \ kexec -l "${cdrom_vmlinuz}" \
--initrd="${custom_initrd}" \ --initrd="${custom_initrd}" \
--append="boot=casper automatic-ubiquity noninteractive noprompt file=/preseed.cfg debian-installer/language=de keyboard-configuration/layoutcode=de quiet splash ---" || --append="boot=casper automatic-ubiquity tuxflotte-autoclick debug-ubiquity noprompt file=/preseed.cfg debian-installer/language=de keyboard-configuration/layoutcode=de quiet splash ---" ||
{ backend_fatal "kexec -l fehlgeschlagen."; return 1; } { backend_fatal "kexec -l fehlgeschlagen."; return 1; }
backend_log "Starte unbeaufsichtigte Installation (kexec -e). Kein Ruecksprung erwartet - ab hier laeuft die eigentliche Installation im neuen Kernel weiter." backend_log "Starte unbeaufsichtigte Installation (kexec -e). Kein Ruecksprung erwartet - ab hier laeuft die eigentliche Installation im neuen Kernel weiter."

View File

@ -29,13 +29,97 @@ d-i partman-auto/method string regular
d-i partman-auto/expert_recipe string ${TUXFLOTTE_PARTMAN_RECIPE} d-i partman-auto/expert_recipe string ${TUXFLOTTE_PARTMAN_RECIPE}
d-i partman-auto/choose_recipe select tuxflotte d-i partman-auto/choose_recipe select tuxflotte
d-i partman-partitioning/confirm_write_new_label boolean true d-i partman-partitioning/confirm_write_new_label boolean true
d-i partman/choose_partition select finish d-i partman-partitioning/confirm_new_label boolean true
# "partman/choose_partition select finish" wurde bewusst entfernt: das ist
# die Frage des MANUELLEN/erweiterten Partitionierers ("Menu" -> "Finish
# partitioning"), keine des gefuehrten/automatischen Ablaufs. Direktes
# Preseeden ohne echten Seitenaufbau (weder im GTK- noch im
# noninteractive-Frontend) fuehrt in ubi-partman.py real reproduzierbar zu
# einer Endlosschleife im internen "building_cache"-Zustandsautomaten der
# choose_partition-Verarbeitung (ueber 100.000 Debconf-Zeilen in wenigen
# Sekunden ohne echten Fortschritt, sowohl mit automatic-ubiquity/GTK als
# auch mit dem verworfenen noninteractive-Frontend - siehe ADR-0023-Nachtrag).
# Ohne diese Zeile uebernehmen partman-auto/method + expert_recipe +
# choose_recipe (oben) die gefuehrte Partitionierung auf dem dafuer
# vorgesehenen Weg.
d-i partman/confirm boolean true d-i partman/confirm boolean true
d-i partman/confirm_nochanges boolean true
d-i partman/confirm_nooverwrite boolean true d-i partman/confirm_nooverwrite boolean true
d-i partman/unmount_active boolean true
d-i partman/automount boolean true
d-i partman/filter_mounted boolean true
d-i partman-partitioning/confirm_resize boolean true
d-i partman-ext3/lazy_itable_init boolean true
d-i partman/boot_not_first_partition boolean true
d-i partman-basicfilesystems/boot_not_first_partition boolean true
d-i partman-basicfilesystems/boot_not_ext2 boolean true
d-i partman-ext3/boot_not_bootable boolean true
d-i partman-ext3/boot_not_ext2_or_ext3 boolean true
d-i partman-basicfilesystems/no_mount_point boolean true
d-i partman-basicfilesystems/no_swap boolean true
d-i partman-basicfilesystems/check_failed boolean true
d-i partman-basicfilesystems/swap_check_failed boolean true
d-i partman-ext3/bad_alignment boolean true
# Dieselbe Polaritaets-Falle wie bei no_bootable_biosgrub weiter unten (siehe
# dortiger Kommentar) - "true" hiesse "Problem besteht wirklich, abbrechen".
# Fuer UEFI-Zielgeraete legt _tuxflotte_render_partman_recipe() bereits eine
# echte ESP an, dieser Fallback sollte also nie greifen.
d-i partman-partitioning/no_bootable_efi boolean false
# Anders als die meisten uebrigen Boolean-Fragen hier bedeutet "true" bei
# no_bootable_biosgrub NICHT "trotzdem fortfahren", sondern "das Problem
# besteht wirklich" -> der pruefende Skript (check.d/08biosgrub) bricht dann
# mit exit 1 ab, was zur Endlosschleife zurueck ins choose_partition-Menue
# fuehrt (real entdeckt und via Quelltext auf dem Live-Medium verifiziert,
# siehe ADR-0023-Nachtrag). Der eigentliche Fix ist eine echte BIOS-Boot-
# Partition im Rezept (siehe _tuxflotte_render_partman_recipe() in
# backend.sh) - "false" hier bleibt nur als defensiver Fallback, falls die
# Partition aus irgendeinem Grund nicht als "biosgrub" erkannt wird.
d-i partman-partitioning/no_bootable_biosgrub boolean false
d-i partman-partitioning/bootable_logical boolean true
d-i partman-partitioning/unknown_label boolean true
d-i partman-partitioning/unsupported_label boolean true
d-i partman-basicmethods/method_only boolean true
d-i grub-installer/only_debian boolean true
d-i grub-installer/with_other_os boolean true
d-i grub-installer/make_active boolean true
d-i grub-installer/grub2_instead_of_grub_legacy boolean true
d-i grub-installer/grub_not_mature_on_this_platform boolean true
d-i grub-installer/multipath boolean true
d-i grub-installer/sataraid boolean true
# Wichtig: false, nicht true -- "skip" heisst hier woertlich "GRUB-Installation
# ueberspringen". true wuerde die Bootloader-Installation aktiv verhindern.
d-i grub-installer/skip boolean false
d-i partman-auto-lvm/no_boot boolean true
d-i partman-target/mount_failed boolean true
# partman-efi/no_efi wird ENTGEGEN der urspruenglichen Annahme sehr wohl
# gefragt, auch im reinen BIOS/SeaBIOS-Betrieb ohne NVRAM (real via
# debug-ubiquity-Log verifiziert, siehe ADR-0023-Nachtrag) -- Ubiquity prueft
# offenbar unabhaengig vom aktuellen Boot-Modus, ob eine EFI-System-Partition
# existiert. "false" heisst hier "trotzdem fortfahren" (die Alternative
# "true" wuerde zurueck ins Partitionierungsmenue springen und den Ablauf
# blockieren -- fuer ein bewusstes BIOS/MBR-Setup ohne EFI-Partition ist
# false die richtige Antwort).
d-i partman-efi/no_efi boolean false
# Bewusst weiterhin NICHT preseeded: grub-installer/force-efi-extra-removable
# (EFI-spezifisch, im BIOS-Betrieb ohne Wirkung) sowie partman-crypto/*,
# partman-lvm/*, partman-jfs/* (Recipe nutzt weder Crypto noch LVM noch JFS,
# koennen also nie auftreten; einige dieser Fragen sind bei "true" destruktiv
# (z.B. crypto_warn_erase), daher hier absichtlich nicht blind auf true
# gesetzt).
ubiquity ubiquity/summary note ubiquity ubiquity/summary note
ubiquity ubiquity/reboot boolean true ubiquity ubiquity/reboot boolean true
ubiquity ubiquity/use_nonfree boolean true ubiquity ubiquity/use_nonfree boolean true
# Ohne diese Zeile stuerzt Ubiquity im automatic-ubiquity-GTK-Modus real
# reproduzierbar ab (TypeError: Argument 1 does not allow None as a value,
# in ubi-prepare.py enable_download_updates() -> label_download_updates.
# set_label(), ausgeloest durch einen globalen Online-Status-Callback, der
# unabhaengig vom Automatik-Modus feuert, obwohl die zugehoerige Seite dort
# nie aufgebaut wird - die Widget-Referenz bleibt None). Die "Waehrend der
# Installation aktualisieren"-Option wird dadurch bewusst deaktiviert;
# funktional kein Verlust, da der Provisioning Agent das System nach der
# Ersteinrichtung ohnehin selbst aktuell haelt.
ubiquity ubiquity/download_updates boolean false
# Pendant zu Fedoras kickstart.tpl %packages (ansible-core, git) - der # Pendant zu Fedoras kickstart.tpl %packages (ansible-core, git) - der
# Provisioning Agent braucht ansible-pull, das wiederum git zum Klonen des # Provisioning Agent braucht ansible-pull, das wiederum git zum Klonen des

View File

@ -35,4 +35,23 @@ if [ -d /root/cdrom/updates ]; then
cp -a /root/cdrom/updates/. /root/ cp -a /root/cdrom/updates/. /root/
fi fi
# Ubiquity stuerzt im automatic-ubiquity-GTK-Modus real reproduzierbar ab
# (TypeError: Argument 1 does not allow None as a value), sobald
# enable_download_updates(False) den Netzwerkstatus als "nicht verbunden"
# meldet: ubi-prepare.py uebergibt das Ergebnis von
# self.controller.get_string('ubiquity/text/label_download_updates_na')
# ungeprueft an GtkLabel.set_label() - fehlt fuer diese Vorlage/Sprache ein
# Uebersetzungsstring, liefert get_string() None statt eines leeren Strings,
# und GTK akzeptiert kein None als Label-Text (real ueber QEMU-Testlauf
# gefunden, siehe ADR-0023-Nachtrag). Gezielter Sed-Patch statt vollstaendigem
# Datei-Ersatz, um nicht die komplette Drittanbieter-Datei mitpflegen zu
# muessen - betrifft nur die eine Zeile, "or ''" faengt jeden None-Rueckgabewert
# ab, unabhaengig von der genauen Ursache der fehlenden Uebersetzung.
ubi_prepare="/root/usr/lib/ubiquity/plugins/ubi-prepare.py"
if [ -f "$ubi_prepare" ]; then
sed -i \
"s/self\.controller\.get_string(template))/self.controller.get_string(template) or '')/" \
"$ubi_prepare"
fi
touch /run/.casper-boot touch /run/.casper-boot

View File

@ -0,0 +1 @@
../tuxflotte-autoclicker.service

View File

@ -0,0 +1,17 @@
[Unit]
Description=Tuxflotte Autoklicker fuer Ubiquitys GTK-Installationsassistenten
# Nur bei automatisierter Installation relevant (siehe autoclicker.sh -
# prueft selbst auf das Boot-Keyword "tuxflotte-autoclick" und beendet sich
# sofort, wenn es fehlt). Bewusst kein "After=graphical.target" o.ae., da
# ubiquity-dm keine normale Display-Manager-Sitzung startet, deren
# Bereitschaft systemd auf ueblichem Weg erkennen wuerde - das Skript selbst
# wartet auf den X-Socket.
After=multi-user.target
[Service]
Type=simple
ExecStart=/opt/tuxflotte/scripts/autoclicker.sh
Restart=no
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,111 @@
#!/bin/bash
### Klickt automatisiert durch Ubiquitys GTK-Installationsassistenten
### (automatic-ubiquity) - noetig, weil Ubiquitys eigenes "noninteractive"-
### Frontend die gefuehrte Partitionierung nicht zuverlaessig automatisieren
### kann (endlose choose_partition-Schleife in ubi-partman.py, real
### bestaetigt, siehe ADR-0023-Nachtrag). Der GTK-Assistent fuellt jede Seite
### bereits vollstaendig aus dem Preseed vor (siehe preseed.tpl) - es fehlt
### nur der "Weiter"/"Installieren"-Klick pro Seite, den dieses Skript per
### xdotool simuliert.
###
### WICHTIG (real beim Testen entdeckt, siehe ADR-0023-Nachtrag): das
### Ubiquity-Fenster heisst NICHT "ubiquity" - der Fenstertitel ist z.B.
### "Installation (as superuser)". Eine Fenstersuche nach dem Namen "ubiquity"
### (fruehere Version dieses Skripts) findet also nie etwas und wurde hier auf
### eine Suche nach JEDEM sichtbaren, betitelten Fenster umgestellt.
###
### NOCH NICHT GELOEST (bewusst als bekannte Einschraenkung stehen gelassen,
### siehe ADR-0023-Nachtrag): auf der Partitionierungs-Uebersichtsseite
### aktiviert "Enter" NICHT den "Jetzt installieren"-Button, sondern einen
### Ausklapp-Pfeil eines darunterliegenden Status-Panels ("Konfiguration der
### Installation wird ueberprueft ..."). Ein Mausklick per xdotool auf
### errechnete Fensterkoordinaten wurde real ausprobiert, aber sowohl die
### Fenstererkennung (mehrere ueberlappende X11-Fenster gleicher/aehnlicher
### Groesse durch Metacity-Dekoration, "groesstes Fenster"-Heuristik traf
### wiederholt das falsche) als auch die Klick-Koordinaten selbst waren nicht
### zuverlaessig genug fuer den produktiven Einsatz - deshalb hier bewusst
### NICHT eingebaut, um kein Risiko falscher Klicks (z.B. auf eine
### "Formatieren?"-Checkbox) einzugehen. Die Enter-Taste bleibt der sicherere
### Kompromiss: sie tut auf den meisten Seiten das Richtige und ist auf dieser
### einen Seite bestenfalls wirkungslos (klappt nur einen Infobereich auf/zu),
### nie destruktiv.
###
### Wird per systemd-Service (siehe ...service im selben Ausliefer-Layer) bei
### JEDEM Boot gestartet, bricht aber sofort ab, wenn das eigene Boot-Keyword
### "tuxflotte-autoclick" nicht in /proc/cmdline steht - siehe backend_launch()
### in backends/mint/backend.sh, wo dieses Keyword gesetzt wird. Auf einem
### normalen (nicht automatisierten) Boot also wirkungslos.
set -u
LOG=/var/log/tuxflotte-autoclicker.log
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') $*" >>"${LOG}"
}
grep -qw tuxflotte-autoclick /proc/cmdline || exit 0
log "tuxflotte-autoclick erkannt, starte Autoklicker."
export DISPLAY=:0
# ubiquity-dm startet X frueh im Boot zu einem nicht exakt vorhersagbaren
# Zeitpunkt - auf den Unix-Socket warten statt auf eine feste Wartezeit zu
# vertrauen.
x_ready=0
for _ in $(seq 1 120); do
if [ -S /tmp/.X11-unix/X0 ]; then
x_ready=1
break
fi
sleep 1
done
if [ "${x_ready}" -ne 1 ]; then
log "X-Server nach 120s nicht erschienen, breche ab."
exit 1
fi
log "X-Server erkannt."
if ! command -v xdotool >/dev/null 2>&1; then
log "xdotool fehlt auf dem Live-Medium, installiere nach."
if ! apt-get install -y xdotool >>"${LOG}" 2>&1; then
log "xdotool-Installation fehlgeschlagen, breche ab."
exit 1
fi
fi
# Bewusst betiteltes Fenster suchen (leerer --name-Ausdruck matcht jeden
# Titel) statt nach "ubiquity" - siehe Kommentar oben, der tatsaechliche
# Fenstertitel enthaelt dieses Wort nie.
main_window() {
xdotool search --onlyvisible --name "" 2>/dev/null | head -n1
}
# Ubiquity-Fenster abwarten, bevor die Klick-Schleife beginnt.
for _ in $(seq 1 60); do
[ -n "$(main_window)" ] && break
sleep 1
done
is_ubiquity_running() {
pgrep -f '/usr/bin/ubiquity' >/dev/null 2>&1
}
log "Starte Klick-Schleife."
# Harte Obergrenze als Sicherheitsnetz (60 Minuten) - falls die Installation
# haengen bleibt, soll dieser Dienst nicht unbegrenzt weiterlaufen.
end=$((SECONDS + 3600))
clicks=0
while [ "${SECONDS}" -lt "${end}" ]; do
if ! is_ubiquity_running; then
log "ubiquity-Prozess nicht mehr aktiv (vermutlich fertig oder abgestuerzt), beende Schleife nach ${clicks} Klick(s)."
break
fi
win="$(main_window)"
if [ -n "${win}" ]; then
xdotool windowactivate --sync "${win}" 2>/dev/null || true
xdotool key --window "${win}" Return 2>/dev/null || true
clicks=$((clicks + 1))
fi
sleep 2
done
log "Autoklicker beendet (${clicks} Klick(s) insgesamt)."

View File

@ -0,0 +1,40 @@
#!/usr/bin/env bash
# Tuxflotte Installer
# Phase 0 Preflight
#
# Stellt sicher, dass Werkzeuge vorhanden sind, die spaetere Module (ab
# 10_hardware.sh) brauchen, aber auf dem Live-Medium selbst (anders als im
# Zielsystem, siehe pkgsel/include in preseed.tpl) nicht vorinstalliert sind.
#
# jq ist der einzige hier betroffene Fall: 10_hardware.sh, 12_enrollment_auth.sh,
# 15_server_handshake.sh, 17_device_status.sh, 20_profile_selection.sh,
# 25_installation_confirm.sh und 30_runtime_blueprint.sh nutzen es alle, das
# erste davon (10_hardware.sh) bereits deutlich vor 40_backend.sh, wo
# backend_init() denselben Nachinstallations-Mechanismus fuer den Kexec-Pfad
# schon kennt (siehe backends/mint/backend.sh) - hier zu spaet fuer die
# frueheren Module. Real entdeckt: beim automatisierten Start ueber
# start-kiosk.sh (kein Terminal, keine sichtbare Fehlermeldung) blieb der
# Installer bereits in 10_hardware.sh mit "Benoetigtes Programm nicht
# gefunden: jq" haengen, sichtbar nur in ~/.xsession-errors - manuelle Testlaeufe
# in dieser Session sind daran nie gescheitert, weil jq dabei stets vorab von
# Hand nachinstalliert wurde, bevor installer.sh gestartet wurde.
set -Eeuo pipefail
readonly SCRIPT_NAME="${0##*/}"
log() {
printf '[%s] %s\n' "${SCRIPT_NAME}" "$*" >&2
}
if ! command -v jq >/dev/null 2>&1; then
log "jq fehlt auf dem Live-Medium, installiere nach."
sed -i '/^deb cdrom/d' /etc/apt/sources.list 2>/dev/null || true
rm -f /etc/apt/sources.list.d/*cdrom* 2>/dev/null || true
apt-get update -qq ||
{ log "FEHLER: apt-get update fehlgeschlagen."; exit 1; }
DEBIAN_FRONTEND=noninteractive apt-get install -y jq ||
{ log "FEHLER: Installation von jq fehlgeschlagen."; exit 1; }
fi