Fix: whiptail-TUI reagiert nicht auf Tastatureingaben bei curl | bash
sudo, aus einer nicht-interaktiven gepipten Shell heraus aufgerufen, gibt die Terminal-Vordergrundgruppe nicht zuverlässig an den Kindprozess weiter. setup.sh lief bisher komplett (inkl. aller whiptail-Dialoge) innerhalb von sudo, wodurch das Menü zwar sichtbar war, aber keine Tasten mehr ankamen. setup.sh fragt jetzt alle interaktiven Eingaben (Stage-Auswahl, Zielbenutzer, Ollama-Pfad) zuerst als normaler Nutzer ab und eskaliert erst danach per exec sudo, wobei die bereits getroffenen Entscheidungen als Flags/Env-Variablen durchgereicht werden. install.sh eskaliert dadurch nicht mehr selbst. Zusätzlich wird die fehlerhafte "-c /dev/tty"-Interaktivitätsprüfung (prüfte nur Existenz der Gerätedatei, nicht ob ein Terminal verbunden ist) durch has_tty() ersetzt. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017WMUd2fGsPCtTCVQkSS5TA
This commit is contained in:
@@ -23,29 +23,31 @@ curl -fsSL https://gitea.creative-dragonslayer.de/Scripts/Setup/raw/branch/main/
|
|||||||
### 2. Manuelles Klonen & Starten
|
### 2. Manuelles Klonen & Starten
|
||||||
Alternativ kann das Repository manuell geklont und ausgeführt werden:
|
Alternativ kann das Repository manuell geklont und ausgeführt werden:
|
||||||
```bash
|
```bash
|
||||||
git clone https://gitea.creative-dragonslayer.de/Scripts/Setup.git && cd Setup && sudo ./setup.sh
|
git clone https://gitea.creative-dragonslayer.de/Scripts/Setup.git && cd Setup && ./setup.sh
|
||||||
```
|
```
|
||||||
Oder direkt vollautomatisch alle Stages (`00` bis `10`) ausführen:
|
Oder direkt vollautomatisch alle Stages (`00` bis `10`) ausführen:
|
||||||
```bash
|
```bash
|
||||||
git clone https://gitea.creative-dragonslayer.de/Scripts/Setup.git && cd Setup && sudo ./setup.sh --all
|
git clone https://gitea.creative-dragonslayer.de/Scripts/Setup.git && cd Setup && ./setup.sh --all
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> `setup.sh` fragt zuerst alle nötigen Eingaben (Modulauswahl, Zielbenutzer, ...) direkt am Terminal ab und eskaliert erst danach selbstständig per `sudo`. Ein manuelles `sudo` davor ist nicht nötig, funktioniert aber ebenfalls.
|
||||||
|
|
||||||
### 3. Interaktiver TUI-Modus
|
### 3. Interaktiver TUI-Modus
|
||||||
Starte das grafische Terminal-Menü (`whiptail`) zur flexiblen Auswahl einzelner Module:
|
Starte das grafische Terminal-Menü (`whiptail`) zur flexiblen Auswahl einzelner Module:
|
||||||
```bash
|
```bash
|
||||||
sudo ./setup.sh
|
./setup.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. Vollautomatischer CLI-Modus
|
### 4. Vollautomatischer CLI-Modus
|
||||||
Führe alle Phasen (`00` bis `10`) ohne Interaktion aus:
|
Führe alle Phasen (`00` bis `10`) ohne Interaktion aus:
|
||||||
```bash
|
```bash
|
||||||
sudo ./setup.sh --all
|
./setup.sh --all
|
||||||
```
|
```
|
||||||
|
|
||||||
### 5. Gezielte Modulauswahl
|
### 5. Gezielte Modulauswahl
|
||||||
Installiere nur bestimmte Phasen (z. B. nur Paketlisten und Schriften):
|
Installiere nur bestimmte Phasen (z. B. nur Paketlisten und Schriften):
|
||||||
```bash
|
```bash
|
||||||
sudo ./setup.sh --stages 04,05
|
./setup.sh --stages 04,05
|
||||||
```
|
```
|
||||||
|
|
||||||
### 6. Simulationslauf (Dry-Run)
|
### 6. Simulationslauf (Dry-Run)
|
||||||
|
|||||||
+6
-19
@@ -110,25 +110,12 @@ main() {
|
|||||||
|
|
||||||
log_success "Repository cloned successfully. Starting setup orchestrator..."
|
log_success "Repository cloned successfully. Starting setup orchestrator..."
|
||||||
|
|
||||||
# Check if dry-run flag is requested
|
# setup.sh itself elevates to root via sudo once it needs it - after all
|
||||||
local is_dry_run=0
|
# interactive TUI/prompts have already run as the current user. Escalating
|
||||||
for arg in "$@"; do
|
# here instead would wrap the whiptail dialogs in sudo, which (when sudo is
|
||||||
if [[ "$arg" == "-d" || "$arg" == "--dry-run" ]]; then
|
# invoked from this non-interactive piped shell) leaves them unable to
|
||||||
is_dry_run=1
|
# receive keystrokes. See setup.sh for details.
|
||||||
break
|
local -a setup_cmd=(./setup.sh "$@")
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# Prepare command to execute setup.sh
|
|
||||||
local -a setup_cmd=()
|
|
||||||
if [[ "$(id -u)" -ne 0 ]] && [[ "$is_dry_run" -eq 0 ]]; then
|
|
||||||
if ! command -v sudo >/dev/null 2>&1; then
|
|
||||||
log_error "sudo is required to run setup.sh. Please install sudo or run as root."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
setup_cmd+=(sudo)
|
|
||||||
fi
|
|
||||||
setup_cmd+=(./setup.sh "$@")
|
|
||||||
|
|
||||||
# Reconnect stdin/stdout to /dev/tty before executing setup.sh if piped
|
# Reconnect stdin/stdout to /dev/tty before executing setup.sh if piped
|
||||||
# (e.g. curl ... | bash), otherwise the interactive TUI receives no keystrokes
|
# (e.g. curl ... | bash), otherwise the interactive TUI receives no keystrokes
|
||||||
|
|||||||
+4
-4
@@ -158,14 +158,14 @@ prompt_target_user() {
|
|||||||
|
|
||||||
local chosen=""
|
local chosen=""
|
||||||
local is_interactive=0
|
local is_interactive=0
|
||||||
if [[ -t 0 || -c /dev/tty ]] && [[ "${DEBIAN_FRONTEND:-}" != "noninteractive" && "${CI:-}" != "1" && "${AUTO_CONFIRM:-}" != "1" ]]; then
|
if { [[ -t 0 ]] || has_tty; } && [[ "${DEBIAN_FRONTEND:-}" != "noninteractive" && "${CI:-}" != "1" && "${AUTO_CONFIRM:-}" != "1" ]]; then
|
||||||
is_interactive=1
|
is_interactive=1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$is_interactive" -eq 1 ]]; then
|
if [[ "$is_interactive" -eq 1 ]]; then
|
||||||
local tty_in="/dev/tty"
|
local tty_in="/dev/tty"
|
||||||
local tty_out="/dev/tty"
|
local tty_out="/dev/tty"
|
||||||
if [[ ! -c /dev/tty ]]; then
|
if ! has_tty; then
|
||||||
tty_in="/dev/stdin"
|
tty_in="/dev/stdin"
|
||||||
tty_out="/dev/stderr"
|
tty_out="/dev/stderr"
|
||||||
fi
|
fi
|
||||||
@@ -243,14 +243,14 @@ prompt_ollama_models_path() {
|
|||||||
local default_path="${OLLAMA_MODELS_DEFAULT:-/mnt/Data/Software/ollama/models}"
|
local default_path="${OLLAMA_MODELS_DEFAULT:-/mnt/Data/Software/ollama/models}"
|
||||||
local chosen=""
|
local chosen=""
|
||||||
local is_interactive=0
|
local is_interactive=0
|
||||||
if [[ -t 0 || -c /dev/tty ]] && [[ "${DEBIAN_FRONTEND:-}" != "noninteractive" && "${CI:-}" != "1" && "${AUTO_CONFIRM:-}" != "1" ]]; then
|
if { [[ -t 0 ]] || has_tty; } && [[ "${DEBIAN_FRONTEND:-}" != "noninteractive" && "${CI:-}" != "1" && "${AUTO_CONFIRM:-}" != "1" ]]; then
|
||||||
is_interactive=1
|
is_interactive=1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$is_interactive" -eq 1 ]]; then
|
if [[ "$is_interactive" -eq 1 ]]; then
|
||||||
local tty_in="/dev/tty"
|
local tty_in="/dev/tty"
|
||||||
local tty_out="/dev/tty"
|
local tty_out="/dev/tty"
|
||||||
if [[ ! -c /dev/tty ]]; then
|
if ! has_tty; then
|
||||||
tty_in="/dev/stdin"
|
tty_in="/dev/stdin"
|
||||||
tty_out="/dev/stderr"
|
tty_out="/dev/stderr"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -37,10 +37,14 @@ ensure_term
|
|||||||
# Show help text
|
# Show help text
|
||||||
show_help() {
|
show_help() {
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
Usage: sudo ./setup.sh [OPTIONS]
|
Usage: ./setup.sh [OPTIONS]
|
||||||
|
|
||||||
Debian Unstable Setup & Desktop Customization Framework
|
Debian Unstable Setup & Desktop Customization Framework
|
||||||
|
|
||||||
|
Note: setup.sh elevates itself via sudo once needed, after any interactive
|
||||||
|
prompts have been answered. Run it as your normal desktop user - no need to
|
||||||
|
prefix it with 'sudo' yourself (though doing so still works).
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
-a, --all Run all setup stages sequentially (00 through 10)
|
-a, --all Run all setup stages sequentially (00 through 10)
|
||||||
-s, --stages <list> Comma-separated list of stages to run (e.g. --stages 01,02,04)
|
-s, --stages <list> Comma-separated list of stages to run (e.g. --stages 01,02,04)
|
||||||
@@ -62,10 +66,10 @@ Available Stages:
|
|||||||
10: Hyprland Desktop (LinuxBeginnings Auto-Installer)
|
10: Hyprland Desktop (LinuxBeginnings Auto-Installer)
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
sudo ./setup.sh # Interactive TUI mode
|
./setup.sh # Interactive TUI mode
|
||||||
sudo ./setup.sh --all # Full automated install
|
./setup.sh --all # Full automated install
|
||||||
sudo ./setup.sh --stages 04,05 # Install only packages and fonts
|
./setup.sh --stages 04,05 # Install only packages and fonts
|
||||||
sudo ./setup.sh --stages 01 --dry-run # Dry-run stage 01
|
./setup.sh --stages 01 --dry-run # Dry-run stage 01
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,10 +125,9 @@ if [[ -n "$CLI_USER" ]]; then
|
|||||||
export TARGET_USER="$CLI_USER"
|
export TARGET_USER="$CLI_USER"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Ensure root privileges unless dry-run
|
# NOTE: Root privileges are intentionally NOT required here. All interactive
|
||||||
if [[ "$FLAG_DRY_RUN" -eq 0 ]]; then
|
# prompts (whiptail TUI, target user, Ollama path) must run BEFORE escalating
|
||||||
require_root
|
# to sudo - see the privilege escalation block below for why.
|
||||||
fi
|
|
||||||
|
|
||||||
# Determine stages to run
|
# Determine stages to run
|
||||||
SELECTED_STAGES=()
|
SELECTED_STAGES=()
|
||||||
@@ -181,6 +184,45 @@ if [[ -z "${TARGET_USER:-}" ]]; then
|
|||||||
export TARGET_USER
|
export TARGET_USER
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Pre-resolve the Ollama models path here (while still unprivileged and
|
||||||
|
# directly attached to the terminal) if stage 06 will run, so stage
|
||||||
|
# 06-services.sh never has to prompt again after privilege escalation.
|
||||||
|
if [[ "$FLAG_DRY_RUN" -eq 0 ]] && [[ -z "${OLLAMA_MODELS:-}" ]]; then
|
||||||
|
for st in "${SELECTED_STAGES[@]}"; do
|
||||||
|
if [[ "$st" == "06" ]]; then
|
||||||
|
OLLAMA_MODELS="$(prompt_ollama_models_path)"
|
||||||
|
export OLLAMA_MODELS
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Escalate to root via sudo now that every interactive prompt (whiptail TUI,
|
||||||
|
# target user, Ollama path) has already been answered while directly attached
|
||||||
|
# to the terminal. sudo run from a non-interactive shell (e.g. 'curl | bash')
|
||||||
|
# does not reliably hand the controlling terminal's foreground process group
|
||||||
|
# to the command it execs, which leaves whiptail/read unable to receive any
|
||||||
|
# keystrokes. Running all interactive dialogs before this point, and passing
|
||||||
|
# the already-resolved choices through as flags/env vars, avoids ever needing
|
||||||
|
# terminal input again after the sudo boundary.
|
||||||
|
if [[ "$FLAG_DRY_RUN" -eq 0 ]] && [[ "$(id -u)" -ne 0 ]]; then
|
||||||
|
if ! command_exists sudo; then
|
||||||
|
log_error "sudo is required to run setup.sh. Please install sudo or run as root."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
log_info "Elevating privileges via sudo to continue installation..."
|
||||||
|
joined_stages="$(IFS=,; echo "${SELECTED_STAGES[*]}")"
|
||||||
|
sudo_env_args=("TARGET_USER=$TARGET_USER")
|
||||||
|
if [[ -n "${OLLAMA_MODELS:-}" ]]; then
|
||||||
|
sudo_env_args+=("OLLAMA_MODELS=$OLLAMA_MODELS")
|
||||||
|
fi
|
||||||
|
exec sudo "${sudo_env_args[@]}" bash "$SCRIPT_DIR/setup.sh" --stages "$joined_stages" --user "$TARGET_USER"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$FLAG_DRY_RUN" -eq 0 ]]; then
|
||||||
|
require_root
|
||||||
|
fi
|
||||||
|
|
||||||
# Map stage identifier to script file
|
# Map stage identifier to script file
|
||||||
get_stage_script() {
|
get_stage_script() {
|
||||||
local stage_id="$1"
|
local stage_id="$1"
|
||||||
|
|||||||
Reference in New Issue
Block a user