Der zweite Bootstrap-Lauf brach ab, obwohl beim ersten alles stand: proot-distro hat sein Ablageformat gewechselt — sichtbar an 'Migrating legacy container' — und danach lag das Rootfs nicht mehr dort, wo meine Prüfung nachsah. Sie meldete 'nicht installiert', die folgende Installation scheiterte an 'already installed', und der Lauf brach ab. Ein Fehler in der Erkennung, nicht auf dem Gerät. Geprüft wird jetzt mit 'proot-distro login <distro> -- true'. Das fragt nicht, wo etwas liegt oder wie eine Ausgabe formatiert ist, sondern ob es funktioniert — und überlebt damit auch den nächsten Formatwechsel. Zusätzlich gilt 'already installed' nicht mehr als Fehler: entscheidend ist allein, ob die Anmeldung danach klappt. Tut sie es nicht, nennt das Skript die Handgriffe zum Neuaufsetzen, statt nur abzubrechen. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
155 lines
5.4 KiB
Bash
Executable File
155 lines
5.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# Gemeinsame Hilfsfunktionen für die Phase-0-Spike-Skripte.
|
||
# Wird von den 0x-Skripten eingebunden, nicht direkt ausgeführt.
|
||
|
||
# Farben nur wenn wir auf einem Terminal landen — sonst verschmutzen sie das Protokoll.
|
||
if [ -t 1 ]; then
|
||
C_OK=$'\033[32m'; C_WARN=$'\033[33m'; C_ERR=$'\033[31m'
|
||
C_HEAD=$'\033[1;36m'; C_DIM=$'\033[2m'; C_OFF=$'\033[0m'
|
||
else
|
||
C_OK=""; C_WARN=""; C_ERR=""; C_HEAD=""; C_DIM=""; C_OFF=""
|
||
fi
|
||
|
||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||
OUT_DIR="$REPO_ROOT/spike/out"
|
||
mkdir -p "$OUT_DIR"
|
||
|
||
# Jeder Lauf bekommt sein eigenes Protokoll. Die Sammlung ist später die halbe
|
||
# Auswertung — deshalb wird alles mitgeschrieben, auch was funktioniert hat.
|
||
LOG="${LOG:-$OUT_DIR/$(basename "${0%.sh}").log}"
|
||
|
||
log() { printf '%s\n' "$*" | tee -a "$LOG"; }
|
||
section() { log ""; log "${C_HEAD}══ $* ══${C_OFF}"; }
|
||
ok() { log "${C_OK} ✓${C_OFF} $*"; }
|
||
warn() { log "${C_WARN} !${C_OFF} $*"; }
|
||
fail() { log "${C_ERR} ✗${C_OFF} $*"; }
|
||
hint() { log "${C_DIM} $*${C_OFF}"; }
|
||
|
||
# Befehl ausführen, Ausgabe ins Protokoll, Fehler nicht tödlich.
|
||
# Für alles, was scheitern DARF, ohne den Spike abzubrechen.
|
||
try() {
|
||
log "${C_DIM} \$ $*${C_OFF}"
|
||
if "$@" >>"$LOG" 2>&1; then
|
||
return 0
|
||
else
|
||
local rc=$?
|
||
warn "fehlgeschlagen (Code $rc): $*"
|
||
return $rc
|
||
fi
|
||
}
|
||
|
||
# Wie try(), aber ein Fehlschlag beendet den Spike. Für echte Voraussetzungen.
|
||
need() {
|
||
log "${C_DIM} \$ $*${C_OFF}"
|
||
if ! "$@" >>"$LOG" 2>&1; then
|
||
fail "Abbruch — notwendiger Schritt fehlgeschlagen: $*"
|
||
log ""
|
||
log "Vollständiges Protokoll: $LOG"
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
have() { command -v "$1" >/dev/null 2>&1; }
|
||
|
||
in_termux() {
|
||
case "${PREFIX:-}" in
|
||
*com.termux*) [ -d "$PREFIX/bin" ] ;;
|
||
*) return 1 ;;
|
||
esac
|
||
}
|
||
|
||
require_termux() {
|
||
if ! in_termux; then
|
||
fail "Dieses Skript läuft in Termux auf dem Telefon, nicht auf dem PC."
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
# Prüft, ob die Grundlage steht, BEVOR ein Beweis losläuft. Ohne das scheitert ein
|
||
# Test mitten im Ablauf und sieht aus wie ein inhaltlicher Fehlschlag, obwohl nur
|
||
# die Vorbereitung fehlt — die irreführendste Sorte Fehler.
|
||
voraussetzungen_pruefen() {
|
||
local distro="${1:-debian}" fehlt=0
|
||
|
||
section "Voraussetzungen"
|
||
|
||
if ! have proot-distro; then
|
||
fail "proot-distro ist nicht installiert"
|
||
hint "Nachholen mit: bash spike/00-bootstrap-termux.sh"
|
||
return 1
|
||
fi
|
||
|
||
# 'cannot execute: required file not found' heißt NICHT, dass das Skript fehlt.
|
||
# Es heißt, dass der Interpreter aus seiner Shebang-Zeile fehlt. Der Unterschied
|
||
# kostet sonst eine halbe Stunde Suche an der falschen Stelle.
|
||
local pfad interpreter
|
||
pfad="$(command -v proot-distro)"
|
||
if ! proot-distro list >/dev/null 2>&1; then
|
||
fail "proot-distro lässt sich nicht ausführen"
|
||
interpreter="$(head -1 "$pfad" 2>/dev/null | sed 's|^#!||; s| .*||')"
|
||
log " Datei: $pfad"
|
||
log " Shebang: ${interpreter:-(keine)}"
|
||
if [ -n "$interpreter" ] && [ ! -x "$interpreter" ]; then
|
||
fail "Der Interpreter $interpreter fehlt oder ist nicht ausführbar."
|
||
hint "Das ist die Ursache, nicht proot-distro selbst."
|
||
hint "Reparieren mit: pkg install -y bash coreutils proot proot-distro"
|
||
else
|
||
hint "Reparieren mit: pkg reinstall -y proot-distro"
|
||
fi
|
||
return 1
|
||
fi
|
||
ok "proot-distro ausführbar"
|
||
|
||
# Anmeldeversuch statt Pfad- oder Ausgabeprüfung: proot-distro hat sein
|
||
# Ablageformat gewechselt, und danach lag das Rootfs woanders als erwartet.
|
||
# Diese Prüfung fragt nicht, wo etwas liegt, sondern ob es funktioniert.
|
||
if proot-distro login "$distro" -- true >/dev/null 2>&1; then
|
||
ok "$distro-Rootfs lauffähig"
|
||
else
|
||
fail "$distro-Rootfs fehlt oder startet nicht"
|
||
hint "Nachholen mit: bash spike/00-bootstrap-termux.sh"
|
||
fehlt=1
|
||
fi
|
||
|
||
return $fehlt
|
||
}
|
||
|
||
# Fragt am Ende jedes Beweises nach dem, was nur ein Mensch beurteilen kann:
|
||
# ob es tatsächlich funktioniert hat. Das Ergebnis geht ins Protokoll.
|
||
verdict() {
|
||
local beweis="$1" frage="$2"
|
||
log ""
|
||
log "${C_HEAD}── Beurteilung $beweis ──${C_OFF}"
|
||
log "$frage"
|
||
printf ' [j] ja [n] nein [t] teilweise > '
|
||
read -r antwort </dev/tty || antwort="?"
|
||
local text
|
||
case "$antwort" in
|
||
j|J) text="BESTANDEN" ;;
|
||
n|N) text="GESCHEITERT" ;;
|
||
t|T) text="TEILWEISE" ;;
|
||
*) text="UNKLAR" ;;
|
||
esac
|
||
printf ' Anmerkung (eine Zeile, Enter für nichts) > '
|
||
read -r notiz </dev/tty || notiz=""
|
||
log " Ergebnis $beweis: $text ${notiz:+— $notiz}"
|
||
printf '%s\t%s\t%s\n' "$beweis" "$text" "$notiz" >>"$OUT_DIR/ergebnisse.tsv"
|
||
log ""
|
||
log "Ins Protokoll übertragen: docs/spike-protokoll.md"
|
||
log "Rohdaten: $LOG"
|
||
}
|
||
|
||
# Gerätesteckbrief — landet in jedem Protokoll, damit Meldungen vergleichbar sind.
|
||
geraete_steckbrief() {
|
||
section "Gerät"
|
||
local p
|
||
for p in ro.product.manufacturer ro.product.model ro.product.device \
|
||
ro.build.version.release ro.build.version.sdk ro.board.platform \
|
||
ro.hardware ro.soc.model; do
|
||
log " $p = $(getprop "$p" 2>/dev/null || echo '?')"
|
||
done
|
||
log " Arch = $(uname -m)"
|
||
log " Kernel = $(uname -r)"
|
||
if have free; then log " RAM = $(free -h 2>/dev/null | awk '/Mem:/{print $2}')"; fi
|
||
}
|