Compare commits

...

3 Commits

Author SHA1 Message Date
stornic56 f0cea296d7 fix harden hardware detection D3cold freezes
Fixes a critical startup crash on hybrid graphics laptops (e.g., Intel + Nvidia) running fresh Debian installs without proprietary drivers. 

When the secondary GPU enters D3cold power state, kernel-level I/O operations (like `lspci` or reading `/sys/block/`) hang in Uninterruptible Sleep (State D), ignoring standard kill signals and freezing the terminal. Combined with `set -euo pipefail`, these hangs made the script silently fail or enter infinite loops.

Changes:
- Timeout Wrappers: Wrapped all hardware probing commands (`lspci`, `lsblk`, `cat /sys/...`, `ip`, `iwgetid`, `pw-cli`) with `timeout 2` to force-continue if the kernel blocks.
- Pipeline Safety: Added `|| true` to `nvidia-smi` and `dpkg` fallback queries to prevent `pipefail` from killing the script when drivers are missing.
- Loop Hardening: Fixed an infinite loop in `detect_gpu()` where empty `lspci` outputs caused by timeouts would loop forever by adding `[[ -z "$line" ]] && continue`.
- TUI Fallbacks: Added default values for `${LINES:-24}` and `${COLUMNS:-80}` to prevent `set -u` from crashing the `whiptail` menu in restricted shell environments.
2026-07-26 01:15:57 -05:00
stornic56 762285f993 fix script
-fix script and nvidia-smi
2026-07-25 22:53:18 -05:00
stornic56 cd965a6678 bash gpu detection fix & nvidia-smi hardening
- Fixed critical script termination on hybrid GPU systems (Intel+Nvidia). The `set -euo pipefail` header was causing immediate exit when `read` reached EOF with exit code 1, preventing further execution despite valid hardware detection.
- Added `|| true` to the lspci processing loop in `modules/utils.sh`. This forces the while read condition to always return success (0), allowing clean loop termination and proper variable assignment for `HAS_NVIDIA=true` and `HAS_INTEL=true`.
- Hardened nvidia-smi driver version query with timeout protection. Wrapped the command call with `|| true` to capture exit code 124 from `timeout`, preventing script abortion when GPU enters D3cold state or command fails.
- Changes applied at line 204 (while read loop) and line 243 (nvidia-smi query). Both modifications ensure the main script continues execution after hardware detection completes, enabling full menu loading on dual-GPU laptops.
2026-07-25 22:03:13 -05:00
7 changed files with 39 additions and 38 deletions
+2 -2
View File
@@ -46,8 +46,8 @@ DEBIAN_CODENAME=""
main_menu() { main_menu() {
# Auto-adjust TUI dimensions for small terminals # Auto-adjust TUI dimensions for small terminals
if [ "${LINES:-24}" -lt $((TUI_ALTO + 6)) ] || [ "${COLUMNS:-80}" -lt $((TUI_ANCHO + 6)) ]; then if [ "${LINES:-24}" -lt $((TUI_ALTO + 6)) ] || [ "${COLUMNS:-80}" -lt $((TUI_ANCHO + 6)) ]; then
TUI_ALTO=$((LINES - 4 > 8 ? LINES - 4 : 8)) TUI_ALTO=$(( ${LINES:-24} - 4 > 8 ? ${LINES:-24} - 4 : 8))
TUI_ANCHO=$((COLUMNS - 4 > 50 ? COLUMNS - 4 : 50)) TUI_ANCHO=$(( ${COLUMNS:-80} - 4 > 50 ? ${COLUMNS:-80} - 4 : 50))
TUI_ALTO_LISTA=$((TUI_ALTO - 10 > 4 ? TUI_ALTO - 10 : 4)) TUI_ALTO_LISTA=$((TUI_ALTO - 10 > 4 ? TUI_ALTO - 10 : 4))
fi fi
+2 -2
View File
@@ -225,7 +225,7 @@ _cat_general() {
fi fi
;; ;;
nvme-cli) nvme-cli)
if ! lsblk -d -o TRAN 2>/dev/null | grep -q "^nvme$"; then if ! timeout 2 lsblk -d -o TRAN 2>/dev/null | grep -q "^nvme$"; then
echo "No NVMe controller detected. Skipping." echo "No NVMe controller detected. Skipping."
continue continue
fi fi
@@ -235,7 +235,7 @@ _cat_general() {
local nvme_devs=() local nvme_devs=()
while read -r dev; do while read -r dev; do
nvme_devs+=("$dev") nvme_devs+=("$dev")
done < <(lsblk -d -o NAME,TRAN 2>/dev/null | awk '$2 == "nvme" {print $1}') done < <(timeout 2 lsblk -d -o NAME,TRAN 2>/dev/null | awk '$2 == "nvme" {print $1}')
if [ ${#nvme_devs[@]} -eq 0 ]; then if [ ${#nvme_devs[@]} -eq 0 ]; then
echo "No NVMe block devices found for health check." echo "No NVMe block devices found for health check."
continue continue
+2 -2
View File
@@ -17,7 +17,7 @@ _detect_all_network_devices() {
PCI_NET_DEVS=() PCI_NET_DEVS=()
while IFS= read -r line; do while IFS= read -r line; do
PCI_NET_DEVS+=("$line") PCI_NET_DEVS+=("$line")
done < <(lspci -nn 2>/dev/null | grep -iE 'network controller|ethernet controller' || true) done < <(timeout 2 lspci -nn 2>/dev/null | grep -iE 'network controller|ethernet controller' || true)
USB_WIFI_DEVS=() USB_WIFI_DEVS=()
while IFS= read -r line; do while IFS= read -r line; do
@@ -29,7 +29,7 @@ _detect_all_network_devices() {
PCI_BT_DEVS=() PCI_BT_DEVS=()
while IFS= read -r line; do while IFS= read -r line; do
PCI_BT_DEVS+=("$line") PCI_BT_DEVS+=("$line")
done < <(lspci -nn 2>/dev/null | grep -i 'Bluetooth controller' || true) done < <(timeout 2 lspci -nn 2>/dev/null | grep -i 'Bluetooth controller' || true)
USB_BT_DEVS=() USB_BT_DEVS=()
while IFS= read -r line; do while IFS= read -r line; do
+2 -2
View File
@@ -61,7 +61,7 @@ _install_amd_intel_stack() {
local desc local desc
desc=$(echo "$gpu_line" | sed -E 's/.*: //; s/ *\(rev.*//') desc=$(echo "$gpu_line" | sed -E 's/.*: //; s/ *\(rev.*//')
plan+=" GPU ${gpu_count}: ${desc}\n" plan+=" GPU ${gpu_count}: ${desc}\n"
done < <(lspci -nn | grep -E "VGA|3D" || true) done < <(timeout 2 lspci -nn | grep -E "VGA|3D" || true)
plan+="\nPlanned components:\n" plan+="\nPlanned components:\n"
if $HAS_INTEL; then if $HAS_INTEL; then
local _gen; _gen=$(get_intel_generation) local _gen; _gen=$(get_intel_generation)
@@ -165,7 +165,7 @@ _install_nvidia_stack() {
local desc local desc
desc=$(echo "$gpu_line" | sed -E 's/.*: //; s/ *\(rev.*//') desc=$(echo "$gpu_line" | sed -E 's/.*: //; s/ *\(rev.*//')
plan+=" GPU ${gpu_count}: ${desc}\n" plan+=" GPU ${gpu_count}: ${desc}\n"
done < <(lspci -nn | grep -E "VGA|3D" || true) done < <(timeout 2 lspci -nn | grep -E "VGA|3D" || true)
plan+="\nPlanned:\n [+] NVIDIA proprietary driver" plan+="\nPlanned:\n [+] NVIDIA proprietary driver"
_msg "NVIDIA Stack — Plan" "$plan" 14 65 _msg "NVIDIA Stack — Plan" "$plan" 14 65
+6 -6
View File
@@ -3,7 +3,7 @@
is_nvidia_kepler() { is_nvidia_kepler() {
local dev_id local dev_id
dev_id=$(lspci -nn | grep -iE "VGA|3D" | grep -i nvidia | grep -oP '10de:\K[0-9a-fA-F]+' | head -n1) dev_id=$(timeout 2 lspci -nn | grep -iE "VGA|3D" | grep -i nvidia | grep -oP '10de:\K[0-9a-fA-F]+' | head -n1)
[ -z "$dev_id" ] && { echo false; return; } [ -z "$dev_id" ] && { echo false; return; }
local dev_int local dev_int
@@ -23,7 +23,7 @@ is_nvidia_kepler() {
is_nvidia_fermi() { is_nvidia_fermi() {
local dev_id local dev_id
dev_id=$(lspci -nn | grep -iE "VGA|3D" | grep -i nvidia | grep -oP '10de:\K[0-9a-fA-F]+' | head -n1) dev_id=$(timeout 2 lspci -nn | grep -iE "VGA|3D" | grep -i nvidia | grep -oP '10de:\K[0-9a-fA-F]+' | head -n1)
[ -z "$dev_id" ] && { echo false; return; } [ -z "$dev_id" ] && { echo false; return; }
local dev_int local dev_int
@@ -56,7 +56,7 @@ is_nvidia_fermi() {
is_nvidia_maxwell() { is_nvidia_maxwell() {
local dev_id local dev_id
dev_id=$(lspci -nn | grep -iE "VGA|3D" | grep -i nvidia | grep -oP '10de:\K[0-9a-fA-F]+' | head -n1) dev_id=$(timeout 2 lspci -nn | grep -iE "VGA|3D" | grep -i nvidia | grep -oP '10de:\K[0-9a-fA-F]+' | head -n1)
[ -z "$dev_id" ] && { echo false; return; } [ -z "$dev_id" ] && { echo false; return; }
local dev_int local dev_int
@@ -76,7 +76,7 @@ is_nvidia_maxwell() {
is_nvidia_pascal() { is_nvidia_pascal() {
local dev_id local dev_id
dev_id=$(lspci -nn | grep -iE "VGA|3D" | grep -i nvidia | grep -oP '10de:\K[0-9a-fA-F]+' | head -n1) dev_id=$(timeout 2 lspci -nn | grep -iE "VGA|3D" | grep -i nvidia | grep -oP '10de:\K[0-9a-fA-F]+' | head -n1)
[ -z "$dev_id" ] && { echo false; return; } [ -z "$dev_id" ] && { echo false; return; }
local dev_int local dev_int
@@ -98,7 +98,7 @@ is_nvidia_pascal() {
is_nvidia_blackwell() { is_nvidia_blackwell() {
local dev_id local dev_id
dev_id=$(lspci -nn | grep -iE "VGA|3D" | grep -i nvidia | grep -oP '10de:\K[0-9a-fA-F]+' | head -n1) dev_id=$(timeout 2 lspci -nn | grep -iE "VGA|3D" | grep -i nvidia | grep -oP '10de:\K[0-9a-fA-F]+' | head -n1)
[ -z "$dev_id" ] && { echo false; return; } [ -z "$dev_id" ] && { echo false; return; }
local dev_int local dev_int
@@ -114,7 +114,7 @@ is_nvidia_blackwell() {
is_amd_legacy_gcn() { is_amd_legacy_gcn() {
local dev_id local dev_id
dev_id=$(lspci -nn | grep -iE "VGA|3D" | grep -i amd | grep -oP '1002:\K[0-9a-fA-F]{4}' | head -n1) dev_id=$(timeout 2 lspci -nn | grep -iE "VGA|3D" | grep -i amd | grep -oP '1002:\K[0-9a-fA-F]{4}' | head -n1)
[ -z "$dev_id" ] && { echo false; return; } [ -z "$dev_id" ] && { echo false; return; }
local legacy_ids local legacy_ids
+9 -9
View File
@@ -27,7 +27,7 @@ _show_sysinfo() {
if echo "$gpu_line" | grep -qi "nvidia"; then if echo "$gpu_line" | grep -qi "nvidia"; then
local nv_ver="" local nv_ver=""
nv_ver=$(nvidia-smi --query-gpu=driver_version --format=csv,noheader 2>/dev/null | head -1) nv_ver=$(timeout 3 nvidia-smi --query-gpu=driver_version --format=csv,noheader 2>/dev/null | head -1)
[ -z "$nv_ver" ] && nv_ver=$(dpkg -l nvidia-driver 2>/dev/null | awk '/^ii/ {print $3}' | sed 's/-.*//') [ -z "$nv_ver" ] && nv_ver=$(dpkg -l nvidia-driver 2>/dev/null | awk '/^ii/ {print $3}' | sed 's/-.*//')
msg+="GPU ${gpu_count}: ${desc}\n" msg+="GPU ${gpu_count}: ${desc}\n"
msg+=" Driver: ${nv_ver:+NVIDIA }${nv_ver:-not installed}\n" msg+=" Driver: ${nv_ver:+NVIDIA }${nv_ver:-not installed}\n"
@@ -37,7 +37,7 @@ _show_sysinfo() {
msg+="GPU ${gpu_count}: ${desc}\n" msg+="GPU ${gpu_count}: ${desc}\n"
msg+=" Driver: ${mesa_ver:+Mesa }${mesa_ver:-unknown}\n" msg+=" Driver: ${mesa_ver:+Mesa }${mesa_ver:-unknown}\n"
fi fi
done < <(lspci -nn | grep -E "VGA|3D" || true) done < <(timeout 2 lspci -nn | grep -E "VGA|3D" || true)
fi fi
if ! $found_gpu; then if ! $found_gpu; then
@@ -52,13 +52,13 @@ _show_sysinfo() {
declare -a pci_eth_lines=() declare -a pci_eth_lines=()
while IFS= read -r line; do while IFS= read -r line; do
pci_eth_lines+=("$line") pci_eth_lines+=("$line")
done < <(lspci -d ::0200 2>/dev/null || true) done < <(timeout 2 lspci -d ::0200 2>/dev/null || true)
# ── 2. Detect ALL WiFi chipsets (class 0x0280 + vendor fallbacks) ── # ── 2. Detect ALL WiFi chipsets (class 0x0280 + vendor fallbacks) ──
declare -a pci_wifi_lines=() declare -a pci_wifi_lines=()
while IFS= read -r line; do while IFS= read -r line; do
pci_wifi_lines+=("$line") pci_wifi_lines+=("$line")
done < <(lspci -d ::0280 2>/dev/null || true) done < <(timeout 2 lspci -d ::0280 2>/dev/null || true)
# Broadcom vendor-ID fallback (14e4) — include only if not already captured # Broadcom vendor-ID fallback (14e4) — include only if not already captured
while IFS= read -r line; do while IFS= read -r line; do
@@ -69,7 +69,7 @@ _show_sysinfo() {
done done
! $already && pci_wifi_lines+=("$line") ! $already && pci_wifi_lines+=("$line")
fi fi
done < <(lspci -nn 2>/dev/null || true) done < <(timeout 2 lspci -nn 2>/dev/null || true)
# USB WiFi fallback # USB WiFi fallback
local usb_wifi_lines=() local usb_wifi_lines=()
@@ -112,7 +112,7 @@ _show_sysinfo() {
lo|docker*|veth*|br-*|virbr*|tun*|tap*|bond*) continue ;; lo|docker*|veth*|br-*|virbr*|tun*|tap*|bond*) continue ;;
esac esac
ip4=$(ip -4 -o addr show "$iface" 2>/dev/null | awk '{print $4}') ip4=$(timeout 2 ip -4 -o addr show "$iface" 2>/dev/null | awk '{print $4}')
# Determine type by PCI class (most reliable) # Determine type by PCI class (most reliable)
local pci_class="" local pci_class=""
@@ -129,7 +129,7 @@ _show_sysinfo() {
desc="${wifi_descs[0]:-Unknown WiFi chipset}" desc="${wifi_descs[0]:-Unknown WiFi chipset}"
shown_wifi_descs+=("${wifi_descs[0]}") shown_wifi_descs+=("${wifi_descs[0]}")
ssid="" ssid=""
[ "$state" = "UP" ] && ssid=$(iwgetid -r "$iface" 2>/dev/null || true) [ "$state" = "UP" ] && ssid=$(timeout 2 iwgetid -r "$iface" 2>/dev/null || true)
;; ;;
*) *)
# Fallback: classify by interface name pattern # Fallback: classify by interface name pattern
@@ -139,7 +139,7 @@ _show_sysinfo() {
desc="${wifi_descs[0]:-Unknown WiFi chipset}" desc="${wifi_descs[0]:-Unknown WiFi chipset}"
shown_wifi_descs+=("${wifi_descs[0]}") shown_wifi_descs+=("${wifi_descs[0]}")
ssid="" ssid=""
[ "$state" = "UP" ] && ssid=$(iwgetid -r "$iface" 2>/dev/null || true) [ "$state" = "UP" ] && ssid=$(timeout 2 iwgetid -r "$iface" 2>/dev/null || true)
;; ;;
eth*|enp*|ens*|enx*|eno*) eth*|enp*|ens*|enx*|eno*)
has_eth=true has_eth=true
@@ -163,7 +163,7 @@ _show_sysinfo() {
else else
msg+="${iface}: ${desc}\n ↓\n" msg+="${iface}: ${desc}\n ↓\n"
fi fi
done < <(ip -o link show 2>/dev/null) done < <(timeout 2 ip -o link show 2>/dev/null)
fi fi
# ── 5. Show chipsets without an active interface ── # ── 5. Show chipsets without an active interface ──
+16 -15
View File
@@ -191,7 +191,7 @@ detect_kernel() {
# ---------------------------------- # ----------------------------------
detect_gpu() { detect_gpu() {
local gpu_lines local gpu_lines
gpu_lines=$(lspci -nn | grep -E "VGA|3D") || true gpu_lines=$(timeout 2 lspci -nn | grep -E "VGA|3D") || true
if [ -z "$gpu_lines" ]; then if [ -z "$gpu_lines" ]; then
GPU_TYPE="unknown" GPU_TYPE="unknown"
GPU_DESC="No GPU detected" GPU_DESC="No GPU detected"
@@ -201,7 +201,8 @@ detect_gpu() {
local has_nvidia=false has_amd=false has_intel=false local has_nvidia=false has_amd=false has_intel=false
local desc_lines="" nvidia_dev_id="" intel_dev_id="" local desc_lines="" nvidia_dev_id="" intel_dev_id=""
while IFS= read -r line; do while IFS= read -r line || [[ -n "$line" ]]; do
[[ -z "$line" ]] && continue
local desc local desc
desc=$(echo "$line" | sed -E 's/.*: //; s/ *\(rev.*//') desc=$(echo "$line" | sed -E 's/.*: //; s/ *\(rev.*//')
[ -n "$desc_lines" ] && desc_lines+=" + " [ -n "$desc_lines" ] && desc_lines+=" + "
@@ -240,9 +241,9 @@ detect_gpu() {
if [ "$GPU_TYPE" = "nvidia" ]; then if [ "$GPU_TYPE" = "nvidia" ]; then
local nv_ver local nv_ver
nv_ver=$(nvidia-smi --query-gpu=driver_version --format=csv,noheader 2>/dev/null | head -1) nv_ver=$(timeout 3 nvidia-smi --query-gpu=driver_version --format=csv,noheader 2>/dev/null | head -1) || true
if [ -z "$nv_ver" ]; then if [ -z "$nv_ver" ]; then
nv_ver=$(dpkg -l nvidia-driver 2>/dev/null | awk '/^ii/ {print $3}' | sed 's/-.*//') nv_ver=$(dpkg -l nvidia-driver 2>/dev/null | awk '/^ii/ {print $3}' | sed 's/-.*//') || true
fi fi
[ -n "$nv_ver" ] && GPU_VERSION="NVIDIA $nv_ver" [ -n "$nv_ver" ] && GPU_VERSION="NVIDIA $nv_ver"
fi fi
@@ -282,21 +283,21 @@ declare -a WIFI_SSIDS=()
detect_network() { detect_network() {
local eth_line local eth_line
eth_line=$(lspci -nn | grep -i 'Ethernet controller' | head -n1) || true eth_line=$(timeout 2 lspci -nn | grep -i 'Ethernet controller' | head -n1) || true
if [ -n "$eth_line" ]; then if [ -n "$eth_line" ]; then
ETH_DESC=$(echo "$eth_line" | sed -E 's/^.*\]: //; s/ \[[0-9a-fA-F]{4}:[0-9a-fA-F]{4}\]//; s/ \(rev [0-9a-fA-F]+\)//') ETH_DESC=$(echo "$eth_line" | sed -E 's/^.*\]: //; s/ \[[0-9a-fA-F]{4}:[0-9a-fA-F]{4}\]//; s/ \(rev [0-9a-fA-F]+\)//')
fi fi
local wifi_line local wifi_line
# Layer 1: grep by PCI class description text # Layer 1: grep by PCI class description text
wifi_line=$(lspci -nn 2>/dev/null | grep -iE 'network controller|wireless|wi-fi|wlan|802\.11' | head -n1) || true wifi_line=$(timeout 2 lspci -nn 2>/dev/null | grep -iE 'network controller|wireless|wi-fi|wlan|802\.11' | head -n1) || true
# Layer 2: grep by exact PCI class code 0x0280 (Network controller) # Layer 2: grep by exact PCI class code 0x0280 (Network controller)
if [ -z "$wifi_line" ]; then if [ -z "$wifi_line" ]; then
wifi_line=$(lspci -d ::0280 2>/dev/null | head -n1) || true wifi_line=$(timeout 2 lspci -d ::0280 2>/dev/null | head -n1) || true
fi fi
# Layer 3: Broadcom vendor ID fallback (14e4) # Layer 3: Broadcom vendor ID fallback (14e4)
if [ -z "$wifi_line" ]; then if [ -z "$wifi_line" ]; then
wifi_line=$(lspci -nn 2>/dev/null | grep -i '14e4:' | head -n1) || true wifi_line=$(timeout 2 lspci -nn 2>/dev/null | grep -i '14e4:' | head -n1) || true
fi fi
if [ -n "$wifi_line" ]; then if [ -n "$wifi_line" ]; then
WIFI_CHIPSET="$wifi_line" WIFI_CHIPSET="$wifi_line"
@@ -324,16 +325,16 @@ detect_network() {
state=$(echo "$line" | awk '{print $9}') state=$(echo "$line" | awk '{print $9}')
case "$iface" in case "$iface" in
eth*|enp*|ens*|enx*|eno*) eth*|enp*|ens*|enx*|eno*)
ip4=$(ip -4 -o addr show "$iface" 2>/dev/null | awk '{print $4}') ip4=$(timeout 2 ip -4 -o addr show "$iface" 2>/dev/null | awk '{print $4}')
ETH_NAMES+=("$iface") ETH_NAMES+=("$iface")
ETH_STATES+=("$state") ETH_STATES+=("$state")
ETH_IPS+=("${ip4:-}") ETH_IPS+=("${ip4:-}")
ETH_DESCS+=("${ETH_DESC:-}") ETH_DESCS+=("${ETH_DESC:-}")
;; ;;
wl*|wlp*|wlo*|wlan*) wl*|wlp*|wlo*|wlan*)
ip4=$(ip -4 -o addr show "$iface" 2>/dev/null | awk '{print $4}') ip4=$(timeout 2 ip -4 -o addr show "$iface" 2>/dev/null | awk '{print $4}')
ssid="" ssid=""
[ "$state" = "UP" ] && ssid=$(iwgetid -r "$iface" 2>/dev/null || true) [ "$state" = "UP" ] && ssid=$(timeout 2 iwgetid -r "$iface" 2>/dev/null || true)
WIFI_NAMES+=("$iface") WIFI_NAMES+=("$iface")
WIFI_STATES+=("$state") WIFI_STATES+=("$state")
WIFI_IPS+=("${ip4:-}") WIFI_IPS+=("${ip4:-}")
@@ -341,7 +342,7 @@ detect_network() {
WIFI_DESCS+=("${WIFI_DESC:-}") WIFI_DESCS+=("${WIFI_DESC:-}")
;; ;;
esac esac
done < <(ip -o link show 2>/dev/null) done < <(timeout 2 ip -o link show 2>/dev/null)
} }
# --------------------------------------- # ---------------------------------------
@@ -382,7 +383,7 @@ detect_storage() {
elif [ "$rota" = "1" ]; then elif [ "$rota" = "1" ]; then
type="HDD" type="HDD"
else else
rm=$(cat /sys/block/"$name"/removable 2>/dev/null || echo 0) rm=$(timeout 2 cat /sys/block/"$name"/removable 2>/dev/null || echo 0)
if [ "$rm" = "1" ]; then if [ "$rm" = "1" ]; then
type="USB/SD" type="USB/SD"
else else
@@ -390,7 +391,7 @@ detect_storage() {
fi fi
fi fi
parts+=("${size} ${type}") parts+=("${size} ${type}")
done < <(lsblk -d -o NAME,SIZE,ROTA,TYPE -e 7,11 2>/dev/null || true) done < <(timeout 2 lsblk -d -o NAME,SIZE,ROTA,TYPE -e 7,11 2>/dev/null || true)
if [ ${#parts[@]} -eq 0 ]; then if [ ${#parts[@]} -eq 0 ]; then
STORAGE_SUMMARY="No disks detected" STORAGE_SUMMARY="No disks detected"
@@ -422,7 +423,7 @@ detect_desktop_environment() {
# Audio server detection (PipeWire / PulseAudio) # Audio server detection (PipeWire / PulseAudio)
# --------------------------------------- # ---------------------------------------
detect_audio_server() { detect_audio_server() {
if command -v pw-cli &>/dev/null && pw-cli info &>/dev/null 2>&1; then if command -v pw-cli &>/dev/null && timeout 2 pw-cli info &>/dev/null 2>&1; then
AUDIO_SERVER="pipewire" AUDIO_SERVER="pipewire"
elif command -v pactl &>/dev/null; then elif command -v pactl &>/dev/null; then
AUDIO_SERVER="pulseaudio" AUDIO_SERVER="pulseaudio"