native-macos: Downloads-Bibliothek des Docker-Tools als zweite Quelle nutzbar machen

- Neuer Auswahlschritt: Apple-Server (Download) vs. lokale downloads/library
  (Docker-Tool) -- letzteres komplett offline nutzbar.
- InstallAssistant.pkg (Big Sur+) wird per installer -pkg -target / zur
  vollstaendigen Install-App entpackt, danach normaler
  createinstallmedia-Weg.
- BaseSystem.dmg/InstallESD.dmg (bis Catalina) ist bereits ein fertiges
  bootfaehiges Volume -- kein createinstallmedia noetig, stattdessen
  diskutil eraseDisk + asr restore --erase (etablierte Community-Technik).
- Flat-JSON-Parser (sed) fuer meta.json ohne jq/python3-Abhaengigkeit.
- Auswahl-/Verzweigungslogik unter Linux mit simulierter Bibliothek
  end-to-end durchgetestet (beide Modi laufen korrekt bis zum jeweils
  ersten macOS-only-Befehl).
This commit is contained in:
ARIA
2026-07-18 12:04:03 +02:00
parent e4dd003bd6
commit 0d0c137de3
2 changed files with 415 additions and 161 deletions
+80 -44
View File
@@ -1,34 +1,57 @@
# Nativer macOS-Weg (createinstallmedia)
# Nativer macOS-Weg (createinstallmedia / asr)
Alternative zum Docker/Linux-Tool im Projekt-Root — **nur nutzbar, wenn
gerade ein echter Mac zur Verfuegung steht** (macOS 10.15 Catalina oder
neuer). Dafuer bekommst du hierueber den offiziell von Apple sauber
funktionierenden Weg: die echte `createinstallmedia`, statt des
Recovery-Extraktions-Workarounds fuer den Big-Sur+-Pfad im Docker-Tool.
Alternative zum Docker/Linux-Tool im Projekt-Root **nur nutzbar, wenn
gerade ein echter Mac zur Verfuegung steht**. Zwei Quellen fuer den
Installer-Payload stehen zur Auswahl, direkt im Script:
## Warum ein eigenes Script, warum nicht die `downloads/`-Bibliothek wiederverwenden?
1. **Von Apple herunterladen** (macOS 10.15 Catalina oder neuer als Host
noetig) — der offiziell von Apple unterstuetzte Weg ueber
`softwareupdate --fetch-full-installer`.
2. **Aus der lokalen Downloads-Bibliothek des Docker-Tools** — wenn das
ganze Projekt inkl. `downloads/`-Ordner z.B. auf eine externe Platte
kopiert wurde, braucht dieser Weg **kein Internet und keinen erneuten
Download**.
Kurz: **andere Bildformate, nicht kompatibel.**
## Warum ein eigenes Script, warum nicht einfach dd wie das Docker-Tool?
- Das Docker-Tool laedt rohe Katalog-Images (`BaseSystem.dmg` bzw.
`InstallAssistant.pkg`) und schreibt sie per `dd` direkt auf den Stick.
Funktioniert ohne Mac, aber `createinstallmedia` kann mit diesen rohen
Dateien nichts anfangen — es braucht die komplette, fertig gepackte
**"Install macOS X.app"**.
- Der offizielle, von Apple unterstuetzte Weg an genau diese App zu kommen
(auch ohne App-Store-Anmeldung) ist der macOS-Bordbefehl
`softwareupdate --fetch-full-installer`. Das gibt es nur unter echtem
macOS ab Catalina.
Kurz: **`createinstallmedia` (der offiziell unterstuetzte macOS-Weg)
braucht die vollstaendige, fertig gepackte "Install macOS X.app"** —
nicht die rohen Katalog-Dateien, die das Docker-Tool per `dd` schreibt.
Deshalb dieser separate, macOS-native Pfad.
Deshalb ist dieses Script komplett unabhaengig vom `./downloads`-Ordner
des Docker-Tools. Es laedt sich seine App-Kopie selbst, direkt von Apple.
## Wie die Bibliotheks-Wiederverwendung funktioniert
Die `downloads/library/`-Bibliothek des Docker-Tools enthaelt pro
macOS-Version genau eine von zwei Rohdateien (siehe `meta.json` im
jeweiligen Unterordner, Feld `mode`):
- **`InstallAssistant.pkg`** (Big Sur und neuer, `mode: "recovery"`):
Apples eigenes `installer -pkg ... -target /` entpackt daraus die
komplette Install-App (inkl. `createinstallmedia`-Binary) nach
`/Applications` — bestaetigt per Apple-Community-Thread, dass ein
`.pkg`-Installer aus dem Software-Update-Katalog 1:1 dasselbe Paket
ist wie der App-Store-Download. Danach laeuft der normale
`createinstallmedia`-Weg wie bei der Apple-Quelle.
- **`BaseSystem.dmg`/`InstallESD.dmg`** (bis Catalina, `mode:
"legacy_dmg"`): das ist bereits ein fertiges, bootfaehiges Volume.
`createinstallmedia` braucht es gar nicht erst — Apples eigenes
Bordmittel `asr restore --source ... --target ... --erase --noprompt`
schreibt es direkt und sauber auf den Stick (etablierte Technik, siehe
Quellen unten). Kein App-Download, kein `createinstallmedia` noetig.
In beiden Faellen: **kein zweiter Download**, die Datei aus der Bibliothek
wird 1:1 weiterverwendet.
## Zukunftssicherheit
`softwareupdate --list-full-installers` fragt Apples eigene Server live ab
— genau wie der Katalog-Check im Docker-Tool, nur eben Apples eigenes
Tool statt eigenem Parser. Neue macOS-Versionen tauchen automatisch in der
Liste auf, ohne dass hier Code angepasst werden muss.
Bei der Apple-Quelle fragt `softwareupdate --list-full-installers`
Apples eigene Server live ab — genau wie der Katalog-Check im Docker-Tool,
nur eben Apples eigenes Tool statt eigenem Parser. Neue macOS-Versionen
tauchen automatisch in der Liste auf.
Bei der Bibliotheks-Quelle haengt die Auswahl logischerweise davon ab, was
das Docker-Tool zuletzt heruntergeladen hat — dafuer aber komplett ohne
Internetzugriff nutzbar.
## Nutzung
@@ -39,32 +62,45 @@ chmod +x create-stick.sh # falls das Ausfuehr-Bit beim Kopieren verloren ging
```
Fuehrt durch vier Schritte (reines Terminal-Menue, keine externen
Abhaengigkeiten — nur `softwareupdate`, `diskutil`, `PlistBuddy`,
`createinstallmedia`, alles Bordmittel):
Abhaengigkeiten nur `softwareupdate`, `diskutil`, `PlistBuddy`,
`installer`, `asr`, `createinstallmedia`, alles Bordmittel):
1. **Versionsliste** von Apple abrufen, Version auswaehlen.
2. **Download** der vollen Installer-App via `softwareupdate
--fetch-full-installer` (wird uebersprungen, wenn die App schon unter
`/Applications` liegt).
3. **USB-Stick auswaehlen** — Liste nur externer, physischer Laufwerke
1. **Quelle + Version waehlen** — Apple-Server oder lokale Bibliothek
(Pfad wird abgefragt, Default rät `../downloads/library` relativ zum
Script — passt, wenn das komplette Projekt kopiert wurde).
2. **Installer-Payload besorgen** — je nach Quelle/Modus: Download via
`softwareupdate`, Entpacken via `installer -pkg`, oder (legacy_dmg
aus der Bibliothek) gar nichts, das Image liegt schon bereit.
3. **USB-Stick auswaehlen** — Liste nur externer, physischer Laufwerke
(`diskutil list -plist external physical`), danach Sicherheitsabfrage:
exakter Geraetepfad muss nochmal eingetippt werden, bevor irgendwas
geloescht wird.
4. **`createinstallmedia --nointeraction`** laeuft mit `sudo`, live-Ausgabe
im Terminal. Am Ende optional die (mehrere GB grosse) Installer-App
wieder loeschen.
4. **Schreiben** — je nach Modus entweder `createinstallmedia
--nointeraction` (Apple-Quelle und Bibliothek/Big-Sur+) oder
`diskutil eraseDisk` + `asr restore --erase` (Bibliothek,
bis Catalina). Beides mit `sudo`, live-Ausgabe im Terminal.
## Grenzen
- Nur macOS 10.15+ (Catalina oder neuer) als **Host**, auf dem das Script
laeuft — das Zielsystem, auf das installiert wird, kann trotzdem
jede von Apple unterstuetzte Version sein.
- Kein Multiboot-Support (anders als das Docker-Tool) —
`createinstallmedia` erstellt immer einen kompletten Single-Version-Stick.
Waere technisch nachruestbar (mehrere Partitionen, mehrere
`createinstallmedia`-Laeufe mit `--volume` auf je eine Partition), aber
aktuell nicht gebaut.
- Downloads landen unter `/Applications` (Apples Standardverhalten von
`softwareupdate`), nicht im Projektordner — dieser Zweig ist bewusst
nicht auf Portabilitaet/externe Platte ausgelegt wie das Docker-Tool,
sondern auf den einfachsten Weg wenn gerade ein Mac da ist.
laeuft das Zielsystem, auf das installiert wird, kann trotzdem
jede von Apple unterstuetzte Version sein. Diese Einschraenkung gilt nur
fuer die Apple-Download-Quelle (`softwareupdate --fetch-full-installer`);
`installer`/`asr` funktionieren grundsaetzlich auch auf aelteren Hosts.
- Kein Multiboot-Support (anders als das Docker-Tool) —
jeder Lauf erstellt immer einen kompletten Single-Version-Stick.
- **Ungetestet auf echtem Mac.** Die Auswahl-/Verzweigungslogik (Quelle,
Modus-Erkennung ueber `meta.json`) wurde unter Linux mit einer
simulierten Bibliothek end-to-end durchgespielt (`bash -n` sauber,
beide Zweige laufen bis zum jeweils ersten macOS-only-Befehl korrekt
durch). Der eigentliche `installer`/`asr`/`createinstallmedia`-Lauf
selbst ist nur gegen offizielle Apple-Doku/Community-Quellen verifiziert,
nicht live auf einem Mac getestet.
## Quellen (fuer den asr-Weg, live nachgeschlagen)
- Apple Developer/Community — `asr restore` ist das Bordmittel fuer
Block-Level-Restores von Disk Images, seit jeher Teil von macOS.
- Cody Krieger — "Creating bootable macOS Sierra installation media on
macOS Catalina": beschreibt exakt den `diskutil eraseDisk` +
`asr restore --erase`-Ablauf fuer aeltere macOS-Installer.
+241 -23
View File
@@ -1,25 +1,37 @@
#!/bin/bash
#
# create-stick.sh — natives macOS-Terminal-Tool fuer bootfaehige
# Installer-Sticks via Apples eigenem createinstallmedia.
#
# Laeuft NUR auf echtem macOS (10.15 Catalina oder neuer). Nutzt
# ausschliesslich Bordmittel: softwareupdate, diskutil, PlistBuddy,
# Installer-Sticks. Laeuft NUR auf echtem macOS. Nutzt ausschliesslich
# Bordmittel: softwareupdate, diskutil, PlistBuddy, installer, asr,
# createinstallmedia. Kein Homebrew, keine externen Abhaengigkeiten.
#
# Warum ein eigener Pfad neben dem Docker/Linux-Tool im Projekt-Root:
# Das Docker-Tool zieht rohe Katalog-Images (BaseSystem.dmg bzw.
# InstallAssistant.pkg) und schreibt sie per dd — das funktioniert ohne
# Mac, aber createinstallmedia braucht die VOLLSTAENDIGE "Install macOS
# X.app", nicht die rohen Katalog-Dateien. Der offizielle, von Apple
# unterstuetzte Weg an diese App zu kommen OHNE App Store ist
# `softwareupdate --fetch-full-installer`. Deshalb ist dieses Script
# bewusst komplett unabhaengig vom ./downloads/library-Ordner des
# Docker-Tools — beide Formate sind nicht kompatibel zueinander.
# Zwei moegliche QUELLEN fuer den Installer-Payload:
#
# Zukunftssicherheit: `softwareupdate --list-full-installers` fragt
# Apples eigene Server live ab. Neue macOS-Versionen tauchen automatisch
# auf, ohne dass dieses Script angefasst werden muss.
# 1) Apple-Server (Download)
# softwareupdate --fetch-full-installer laedt die komplette
# "Install macOS X.app" direkt von Apple. Danach normaler
# createinstallmedia-Weg. Zukunftssicher: die Versionsliste kommt
# live von Apples eigenen Servern, neue macOS-Versionen tauchen
# automatisch auf.
#
# 2) Lokale Downloads-Bibliothek des Docker/Linux-Tools
# (../downloads/library relativ zu diesem Script, wenn das ganze
# Projekt inkl. Downloads z.B. per externer Platte auf den Mac
# kopiert wurde). Kein Internet noetig, kein erneuter Download.
# Zwei Payload-Formate stecken dort je nach macOS-Version, beide
# werden hier unterstuetzt:
# - InstallAssistant.pkg (Big Sur+): 'installer -pkg ... -target /'
# entpackt daraus die komplette Install-App (inkl.
# createinstallmedia-Binary) nach /Applications -- danach der
# normale createinstallmedia-Weg wie bei Quelle 1.
# - BaseSystem.dmg/InstallESD.dmg (bis Catalina): das ist schon
# ein fertiges, bootfaehiges Volume. createinstallmedia braucht
# es nicht extra -- Apples eigenes 'asr restore' schreibt es
# direkt auf den Stick. Kein App-Download noetig.
#
# So wird aus jeder bereits vom Docker-Tool gebauten Offline-Bibliothek
# (externe Platte, ohne Internet) auch am echten Mac ein bootfaehiger
# Stick, ganz ohne doppelten Download.
set -u
@@ -37,12 +49,58 @@ err() { printf "%s%s%s\n" "$RED" "FEHLER: $1" "$RESET" >&2; }
ok() { printf "%s%s%s\n" "$GREEN" "$1" "$RESET"; }
warn() { printf "%s%s%s\n" "$YELLOW" "$1" "$RESET"; }
# Sehr simpler Flat-JSON-Feld-Extraktor -- reicht fuer die meta.json-Dateien
# der Bibliothek (keine verschachtelten Objekte), spart eine Abhaengigkeit
# zu jq/python3 die auf einem frischen Mac nicht garantiert vorhanden ist.
json_field() {
local file="$1" key="$2"
sed -n 's/.*"'"$key"'":[[:space:]]*"\{0,1\}\([^",}]*\)"\{0,1\}.*/\1/p' "$file" | head -n1
}
# ---------- Vorpruefungen ----------
if [[ "$(uname)" != "Darwin" ]]; then
err "Dieses Script laeuft nur auf echtem macOS (kein Linux, keine VM ohne macOS)."
exit 1
fi
# ---------- Schritt 1: Quelle + Version waehlen ----------
title "macOS USB-Stick-Creator (nativ) — Schritt 1/4: Quelle + Version"
echo "Woher soll der macOS-Installer kommen?"
echo
echo " ${BOLD}1)${RESET} Von Apple herunterladen (braucht Internet, mehrere GB)"
echo " ${BOLD}2)${RESET} Aus lokaler Downloads-Bibliothek (Docker-Tool) verwenden -- kein Internet noetig"
echo
printf "%s0)%s Abbrechen\n" "$BOLD" "$RESET"
echo
read -r -p "Quelle waehlen [Nummer]: " SRC_CHOICE
if [[ "$SRC_CHOICE" == "0" || -z "$SRC_CHOICE" ]]; then
echo "Abgebrochen."
exit 0
fi
SOURCE=""
WRITE_MODE="" # "cim" (createinstallmedia) oder "asr" (direktes Image-Restore)
APP_PATH=""
DMG_PATH=""
LIB_TITLE=""
LIB_VERSION=""
case "$SRC_CHOICE" in
1)
SOURCE="apple"
;;
2)
SOURCE="library"
;;
*)
err "Ungueltige Auswahl."
exit 1
;;
esac
if [[ "$SOURCE" == "apple" ]]; then
if ! command -v softwareupdate >/dev/null 2>&1; then
err "'softwareupdate' nicht gefunden — ungewoehnliches macOS-Setup, Abbruch."
exit 1
@@ -59,8 +117,7 @@ if [[ "$MACOS_VER" == 10.* ]]; then
fi
fi
# ---------- Schritt 1: verfuegbare Installer laden ----------
title "macOS USB-Stick-Creator (nativ) — Schritt 1/4: Verfuegbare Versionen"
echo
echo "Frage Apples Software-Update-Server nach verfuegbaren kompletten Installern ab..."
echo
@@ -108,15 +165,101 @@ fi
SEL_TITLE="${TITLES[$((CHOICE-1))]}"
SEL_VERSION="${VERSIONS[$((CHOICE-1))]}"
WRITE_MODE="cim"
# Apples Titel-Feld liefert z.B. "macOS Sonoma" -> App heisst "Install macOS Sonoma.app"
APP_PATH="/Applications/Install ${SEL_TITLE}.app"
echo
ok "Gewaehlt: ${SEL_TITLE} (${SEL_VERSION})"
ok "Gewaehlt: ${SEL_TITLE} (${SEL_VERSION}) -- Quelle: Apple-Server"
else
echo
DEFAULT_LIB_DIR="$(cd "$(dirname "$0")/.." 2>/dev/null && pwd)/downloads/library"
echo "Pfad zur lokalen Downloads-Bibliothek des Docker-Tools (Ordner mit einem"
echo "Unterordner pro macOS-Version, je mit meta.json + Installer-Datei)."
echo
read -r -p "Pfad [Enter fuer ${DEFAULT_LIB_DIR}]: " LIB_DIR
LIB_DIR="${LIB_DIR:-$DEFAULT_LIB_DIR}"
# ---------- Schritt 2: Download (falls noetig) ----------
title "Schritt 2/4: Installer-App besorgen"
if [[ ! -d "$LIB_DIR" ]]; then
err "Ordner nicht gefunden: ${LIB_DIR}"
exit 1
fi
declare -a LIB_ENTRY_DIRS=()
declare -a LIB_ENTRY_DESC=()
for entry_dir in "$LIB_DIR"/*/; do
[[ -d "$entry_dir" ]] || continue
meta="${entry_dir}meta.json"
[[ -f "$meta" ]] || continue
complete="$(json_field "$meta" complete)"
[[ "$complete" == "true" ]] || continue
et="$(json_field "$meta" title)"
ev="$(json_field "$meta" version)"
emode="$(json_field "$meta" mode)"
esize="$(json_field "$meta" size_bytes)"
esize_gb="?"
if [[ "$esize" =~ ^[0-9]+$ ]]; then
esize_gb="$(( esize / 1000 / 1000 / 1000 ))"
fi
mode_desc="bis Catalina, robust"
[[ "$emode" == "recovery" ]] && mode_desc="Big Sur+, ueber installer-pkg"
LIB_ENTRY_DIRS+=("$entry_dir")
LIB_ENTRY_DESC+=("${et} (${ev}) -- ~${esize_gb} GB, ${mode_desc}")
done
if [[ ${#LIB_ENTRY_DIRS[@]} -eq 0 ]]; then
err "Keine vollstaendigen Installer in ${LIB_DIR} gefunden."
exit 1
fi
echo
echo "In der Bibliothek gefunden:"
echo
for i in "${!LIB_ENTRY_DIRS[@]}"; do
printf " %s%2d)%s %s\n" "$BOLD" "$((i+1))" "$RESET" "${LIB_ENTRY_DESC[$i]}"
done
echo
printf "%s0)%s Abbrechen\n" "$BOLD" "$RESET"
echo
read -r -p "Welche Version verwenden? [Nummer]: " LCHOICE
if [[ "$LCHOICE" == "0" || -z "$LCHOICE" ]]; then
echo "Abgebrochen."
exit 0
fi
if ! [[ "$LCHOICE" =~ ^[0-9]+$ ]] || (( LCHOICE < 1 || LCHOICE > ${#LIB_ENTRY_DIRS[@]} )); then
err "Ungueltige Auswahl."
exit 1
fi
SEL_ENTRY_DIR="${LIB_ENTRY_DIRS[$((LCHOICE-1))]}"
SEL_META="${SEL_ENTRY_DIR}meta.json"
LIB_TITLE="$(json_field "$SEL_META" title)"
LIB_VERSION="$(json_field "$SEL_META" version)"
LIB_MODE="$(json_field "$SEL_META" mode)"
LIB_FILENAME="$(json_field "$SEL_META" filename)"
LIB_PAYLOAD_PATH="${SEL_ENTRY_DIR}${LIB_FILENAME}"
if [[ ! -f "$LIB_PAYLOAD_PATH" ]]; then
err "Payload-Datei nicht gefunden: ${LIB_PAYLOAD_PATH}"
exit 1
fi
if [[ "$LIB_MODE" == "recovery" ]]; then
WRITE_MODE="cim"
else
WRITE_MODE="asr"
DMG_PATH="$LIB_PAYLOAD_PATH"
fi
echo
ok "Gewaehlt: ${LIB_TITLE} (${LIB_VERSION}) -- Quelle: lokale Bibliothek (${LIB_PAYLOAD_PATH})"
fi
# ---------- Schritt 2: Installer-Payload besorgen ----------
title "Schritt 2/4: Installer-Payload besorgen"
if [[ "$SOURCE" == "apple" ]]; then
if [[ -d "$APP_PATH" ]]; then
ok "'${APP_PATH}' existiert bereits — Download wird uebersprungen."
else
@@ -138,12 +281,45 @@ else
fi
ok "Download abgeschlossen: ${APP_PATH}"
fi
elif [[ "$WRITE_MODE" == "cim" ]]; then
# Bibliothek, Big Sur+: InstallAssistant.pkg -> komplette Install-App
# nach /Applications entpacken (Apples Standardverhalten von 'installer').
if [[ -d "$APP_PATH" ]]; then
ok "'${APP_PATH}' existiert bereits — Installer-Lauf wird uebersprungen."
else
echo "Entpacke ${LIB_PAYLOAD_PATH} nach /Applications (installer -pkg, braucht sudo)..."
echo "Das dauert je nach Groesse ein paar Minuten."
echo
sudo installer -pkg "$LIB_PAYLOAD_PATH" -target /
RC=$?
if [[ $RC -ne 0 ]]; then
err "'installer -pkg' fehlgeschlagen ($RC)."
exit 1
fi
if [[ ! -d "$APP_PATH" ]]; then
# Fallback: Apples interner App-Name wich vom Bibliotheks-Titel ab --
# nimm das zuletzt angelegte "Install macOS *.app"-Bundle.
FALLBACK_APP="$(ls -dt /Applications/Install\ macOS*.app 2>/dev/null | head -n1)"
[[ -n "$FALLBACK_APP" ]] && APP_PATH="$FALLBACK_APP"
fi
if [[ ! -d "$APP_PATH" ]]; then
err "Konnte die installierte App nach 'installer -pkg' nicht finden."
echo "Tipp: 'ls /Applications | grep Install' zeigt was tatsaechlich da ist."
exit 1
fi
ok "Installiert: ${APP_PATH}"
fi
else
ok "Bibliothek liefert bereits ein fertiges, bootfaehiges Image (${DMG_PATH}) -- kein App-Download noetig."
fi
if [[ "$WRITE_MODE" == "cim" ]]; then
CIM_BIN="${APP_PATH}/Contents/Resources/createinstallmedia"
if [[ ! -x "$CIM_BIN" ]]; then
err "createinstallmedia nicht gefunden unter: ${CIM_BIN}"
exit 1
fi
fi
# ---------- Schritt 3: Ziel-USB-Stick waehlen ----------
title "Schritt 3/4: USB-Stick auswaehlen"
@@ -209,9 +385,10 @@ if [[ "$CONFIRM" != "/dev/${TARGET_DISK}" ]]; then
exit 1
fi
# ---------- Schritt 4: createinstallmedia ausfuehren ----------
# ---------- Schritt 4: Stick schreiben ----------
title "Schritt 4/4: Stick wird erstellt"
if [[ "$WRITE_MODE" == "cim" ]]; then
echo "App: ${APP_PATH}"
echo "Ziel: /dev/${TARGET_DISK}"
echo
@@ -232,11 +409,52 @@ else
fi
echo
read -r -p "Die heruntergeladene Installer-App (mehrere GB) jetzt loeschen um Platz zu sparen? [j/N]: " CLEAN
read -r -p "Die installierte App (mehrere GB) jetzt wieder loeschen um Platz zu sparen? [j/N]: " CLEAN
if [[ "$CLEAN" =~ ^[jJ]$ ]]; then
sudo rm -rf "$APP_PATH"
ok "Geloescht: ${APP_PATH}"
fi
else
# asr-Pfad: BaseSystem.dmg/InstallESD.dmg ist schon ein fertiges,
# bootfaehiges Volume. Erst Stick neu formatieren (liefert einen
# Mountpunkt), dann Apples 'asr restore' das eigentliche Image drauf
# kopieren lassen -- das re-formatiert dabei nochmal komplett nach dem
# Schema des Quell-Images (--erase). Etablierte Community-Technik fuer
# macOS-Installer bis Catalina ohne createinstallmedia.
echo "Quelle: ${DMG_PATH}"
echo "Ziel: /dev/${TARGET_DISK}"
echo
echo "Formatiere /dev/${TARGET_DISK} neu (HFS+) als Vorbereitung (braucht sudo)..."
sudo diskutil eraseDisk JHFS+ INSTALL "/dev/${TARGET_DISK}"
if [[ $? -ne 0 ]]; then
err "diskutil eraseDisk fehlgeschlagen."
exit 1
fi
VOL_MOUNT="/Volumes/INSTALL"
if [[ ! -d "$VOL_MOUNT" ]]; then
err "Erwarteter Mountpunkt ${VOL_MOUNT} nicht gefunden nach dem Formatieren."
echo "Tipp: 'diskutil list /dev/${TARGET_DISK}' zeigt den tatsaechlichen Zustand."
exit 1
fi
echo
echo "asr restore laeuft jetzt (braucht sudo, dauert typischerweise 10-20 Minuten)..."
echo "Der Stick wird dabei nochmal komplett neu formatiert -- das ist normal."
echo
sudo asr restore --source "$DMG_PATH" --target "$VOL_MOUNT" --erase --noprompt
RC=$?
echo
if [[ $RC -eq 0 ]]; then
ok "Fertig! Der Stick ist bootfaehig."
echo "Am Ziel-Mac: beim Start Option/Alt gedrueckt halten, den Stick im Boot-Picker waehlen."
else
err "asr restore ist mit Fehlercode ${RC} beendet — siehe Ausgabe oben."
exit $RC
fi
fi
echo
ok "Alles erledigt."