Skip to main content

⚙️ tweaksManjaro.sh

#!/bin/bash
# ------------------------------------------------------------------------
# tweaksManjaro.sh (Terminal-Menüversion)
#
# WICHTIG: Nutzung auf eigene Verantwortung – bitte vorher Backups anlegen!
#
# Aufruf: bash tweaksManjaro.sh
# Alternativ: Ausführbar machen mit chmod +x tweaksManjaro.sh und direkt starten: ./tweaksManjaro.sh
# Oder über einen Desktop-Starter (z.B. tweaksManjaro.desktop für KDE)
#
# Hinweis: Das Skript verwendet bei Bedarf sudo – es darf nicht direkt als root gestartet werden!
# ------------------------------------------------------------------------
# Beschreibung:
# Dieses Skript bietet verschiedene System-Tweaks für Manjaro Linux.
# Es ersetzt die ursprüngliche KDE-Version (KDEtweaksManjaro.sh mit kdialog) durch eine rein terminalbasierte Oberfläche.
# Integriertes Logging, schaltbar per Variable LOGGING=true/false,
# speichert in tweaksManjaro-LOG.txt neben dem Script,
# beim Überschreiten von LOG_MAX_BYTES wird nach LOG_OLD_FILE rotiert.
#
# Die wichtigsten Optionen sind:
# - Kernel-Check und Systemaktualisierung
# - AUR-Update via yay
# - Aufräumen von Paket-Caches und verwaisten Paketen
# - Setzen von Zugriffsrechten im Home-Verzeichnis
# - Anzeige von Systeminformationen, Sensorwerten, NVMe S.M.A.R.T. etc.
#
# Hinweis zur Rechtevergabe:
# - zugriffsrechte=0: Es werden nur die Besitzerrechte (chown) rekursiv gesetzt – chmod bleibt unverändert.
# - zugriffsrechte=1: Zusätzlich wird chmod 755 für Verzeichnisse und chmod 644 für Dateien gesetzt,
#   außer für ~/.gnupg – dort wird chmod 700 für Verzeichnisse und chmod 600 für Dateien angewendet.
#   ACHTUNG: Flatpaks, Tor-Browser oder andere Programme, die unter ~/. installiert wurden,
#   können dadurch unbrauchbar werden.
#
# - Unabhängig vom Schalter: Alle .sh, .desktop und .AppImage-Dateien im Home werden ausführbar gemacht (chmod 744).
# - also auch dieses Skript, falls es im Home liegt.
# ------------------------------------------------------------------------

set -uo pipefail
# -e -> Script wird sofort beendet, sobald ein Befehl ≠0 zurückgibt,
#       darum nicht "set -euo pipefail" wegen Logs
set -o errtrace

# Skriptversion anzeigen
version="V25.10.019"

# ===== Logging Setup =====
# Logging schaltbar: true/false
LOGGING=${LOGGING:-true}
# Logdatei neben der Scriptdatei ablegen (unabhängig vom PWD)
LOG_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
LOG_FILE="${LOG_DIR}/tweaksManjaro-LOG.txt"
# Maximale Loggröße (Bytes). Standard: 20 MB
LOG_MAX_BYTES="${LOG_MAX_BYTES:-20000000}"
LOG_OLD_FILE="${LOG_DIR}/tweaksManjaro-LOG_old.txt"

rotate_log() {
    [ "${LOGGING:-}" = "true" ] || return 0
    # Wenn Logdatei zu groß ist, nach .old verschieben (überschreiben erlaubt) und neu beginnen
    local size=0
    if [ -f "${LOG_FILE}" ]; then
        size=$(wc -c < "${LOG_FILE}" 2>/dev/null || echo 0)
    fi
    if [ "${size}" -ge "${LOG_MAX_BYTES}" ]; then
        mv -f "${LOG_FILE}" "${LOG_OLD_FILE}" 2>/dev/null || true
        : > "${LOG_FILE}"
    fi
}

_ts() { date +"%Y-%m-%d %H:%M:%S%z"; }

log_msg() {
    [ "${LOGGING:-}" = "true" ] || return 0
    rotate_log
    local msg="$*"
    printf "[%s] [%s] %s\n" "$(_ts)" "$$" "${msg}" >> "${LOG_FILE}"
}

log_start() {
    [ "${LOGGING:-}" = "true" ] || return 0
    local step="$1"
    STEP_START_EPOCH=$(date +%s)
    log_msg "START: ${step}"
}

log_end() {
    [ "${LOGGING:-}" = "true" ] || return 0
    local step="$1"
    local ec="${2:-$?}"
    local end_epoch=$(date +%s)
    local dur="-"
    if [ -n "${STEP_START_EPOCH:-}" ]; then
        dur=$(( end_epoch - STEP_START_EPOCH ))
    fi
    log_msg "END:   ${step} | exit=${ec} | duration_s=${dur}"
    unset STEP_START_EPOCH
}

on_err_trap() {
    local ec=$?
    local lineno=${BASH_LINENO[0]:-0}
    local cmd=${BASH_COMMAND:-"unknown"}
    log_msg "ERROR: ec=${ec} line=${lineno} cmd=${cmd}"
    return $ec
}

on_exit_trap() {
    local ec=$?
    if [ -n "${CURRENT_STEP_NAME:-}" ] && [ -n "${STEP_START_EPOCH:-}" ]; then
        log_end "${CURRENT_STEP_NAME}" "${ec}"
    fi
    log_msg "EXIT: script exited with ec=${ec}"
}

# Aktivieren der Traps
# WICHTIG: Nicht die bestehenden 'set -uo pipefail' ändern
trap on_err_trap ERR
trap on_exit_trap EXIT
# ===== Ende Logging Setup =====



# Sauberer Abbruch bei STRG+C (nicht während kritischer Befehle wie pacman verwenden, nutze dafür run_protected!)
cleanup() {
    echo
    if [[ -n "${rot:-}" && -n "${reset:-}" ]]; then
        echo -e "${rot}❌ Abbruch durch Benutzer${reset}"
    else
        echo "❌ Abbruch durch Benutzer"
    fi
}
trap 'cleanup; exit 130' INT
trap 'cleanup; exit 143' TERM

run_protected() {
    trap '' INT
    "$@"
    trap 'cleanup; exit 130' INT
}


# Führe einen Befehl "weich" aus: Fehler werden geloggt, terminieren aber NICHT das Menü.
run_soft() {
    # Deaktiviere -e lokal, damit wir den Exit-Code selbst prüfen können
    set +e
    "$@"
    ec=$?
    set -e
    if [ $ec -ne 0 ]; then
        log_msg "WARN: run_soft: cmd='$*' exit=${ec}"
        # Nicht abbrechen: immer 0 zurückgeben
        return 0
    fi
    return 0
}
# Wie run_soft, spiegelt aber stdout/stderr ins Log (wenn LOGGING=true) und erfasst den Exitcode korrekt.
run_soft_logged() {
    set +e
    if [ "${LOGGING:-}" = "true" ]; then
        rotate_log
        "$@" 2>&1 | tee -a "${LOG_FILE}"
        ec=${PIPESTATUS[0]}
        rotate_log
    else
        "$@"
        ec=$?
    fi
    set -e
    if [ $ec -ne 0 ]; then
        log_msg "WARN: run_soft_logged: cmd='$*' exit=${ec}"
        return 0
    fi
    return 0
}

# Automatisch aktivieren, wenn flatpak vorhanden ist
flatpak=0
if command -v flatpak &>/dev/null; then
    flatpak=1
fi

# 1 = Rechtekorrektur aktivieren – nur wenn du weißt, was du tust und den Code unten verstehst!
# 0 = deaktivieren (empfohlen)
zugriffsrechte=0

echo "➤ Dieses Skript benötigt sudo-Rechte. Bitte gib dein Passwort ein:"
sudo -v

# Farb-Variablen gegen Terminals ohne tput-Support absichern
if tput setaf 1 &>/dev/null; then
    blau=$(tput setaf 4)
    gruen=$(tput setaf 2)
    rot=$(tput setaf 1)
    gelb=$(tput setaf 3)
    reset=$(tput sgr0)
else
    blau=""
    gruen=""
    rot=""
    gelb=""
    reset=""
fi

# Skript darf nicht direkt als root oder mit sudo gestartet werden
if [ "$EUID" -eq 0 ]; then
    echo "${rot}Fehler: Bitte das Skript nicht als root oder mit sudo starten!${reset}"
    exit 1
fi

# Prüfe Distribution
if ! grep -qi "manjaro" /etc/os-release; then
    echo "${rot}Nicht Manjaro – Skript wird beendet.${reset}"
    exit 0
fi

# Distro-Name extrahieren
# distro=$(grep -oP '^NAME="\K[^"]+' /etc/os-release)
distro=$(source /etc/os-release && echo "$NAME")

# Manjaro-Version
manjaro_version=$(lsb_release -r -s 2>/dev/null || echo "unbekannt")

# Architekturprüfung
arch=$(uname -m)
case "$arch" in
    x86_64|aarch64|armv7l|i686) ;;
    *)
        echo "${rot}Nicht unterstützte Architektur – Skript wird beendet.${reset}"
        exit 0
        ;;
esac

# Check auf public_html
if [ -d "$HOME/public_html" ]; then
    html=1
else
    html=0
fi

# Branch bestimmen (z.B. stable/testing/unstable)
branch=$(pacman-mirrors -G 2>/dev/null || echo "stable")
# echo "DEBUG: branch wurde ermittelt als '$branch'"

press_enter() {
    read -r -p "Drücke Enter zum Fortfahren..." dummy
}

pakete=(curl yay pacman-contrib lsb-release inxi lm_sensors pacman-mirrors util-linux htop btrfs-progs smartmontools nvme-cli)

# Prüfen, ob NVMe-Geräte vorhanden sind (robust über lsblk oder /sys/class/nvme)
if lsblk -d -o NAME | grep -q '^nvme' || [ -e /sys/class/nvme ]; then
    pakete+=("nvme-cli")
fi

fehlend=()
for pkg in "${pakete[@]}"; do
    if ! pacman -Qi "$pkg" &>/dev/null; then
        fehlend+=("$pkg")
    fi
done

if [ ${#fehlend[@]} -gt 0 ]; then
    echo -e "\n${rot}⚠ Fehlende Pakete:${reset} ${fehlend[*]}"
    echo -e "→ Installation z.B. mit: ${gruen}sudo pacman -S --needed ${fehlend[*]}${reset}\n"
    press_enter
fi

# Funktion: GRUB-Konfiguration aktualisieren
update_grub() {
    echo -e "\nPrüfe GRUB-Konfiguration..."

    updated=0
    if [ -f /boot/grub/grub.cfg ]; then
        echo "→ Aktualisiere GRUB (BIOS)"
        sudo grub-mkconfig -o /boot/grub/grub.cfg && updated=1
    fi
    if [ -f /boot/efi/EFI/manjaro/grub.cfg ]; then
        echo "→ Aktualisiere GRUB (UEFI)"
        sudo grub-mkconfig -o /boot/efi/EFI/manjaro/grub.cfg && updated=1
    fi
    if [ "$updated" -eq 1 ]; then
        echo "${gruen}GRUB-Konfiguration erfolgreich.${reset}"
    else
        echo "${rot}Keine grub.cfg gefunden oder Fehler beim Update.${reset}"
    fi
}

# Funktion: Flatpaks anzeigen, aktualisieren und ungenutzte entfernen
update_flatpak() {
    if [ "$flatpak" -gt 0 ] && command -v flatpak &>/dev/null; then
        echo -e "\n${gelb}➤ Installierte Flatpak-Apps:${reset}"
        app_list=$(flatpak list --app --columns=application | grep -v "Anwendungskennung")
        if [ -n "$app_list" ]; then
            echo "$app_list"
        else
            echo "Keine Flatpak-Apps gefunden."
        fi

        echo -e "\n${gelb}➤ Flatpak-Apps aktualisieren:${reset}"
        run_soft_logged flatpak update -y || echo "Fehler bei Flatpak-Update oder keine Updates verfügbar."

        echo -e "\n${gelb}➤ Ungenutzte Flatpaks entfernen:${reset}"
        if [ "${LOGGING:-}" = "true" ]; then
            flatpak_output=$(flatpak uninstall --unused -y 2>&1 | tee -a "${LOG_FILE}")
        else
            flatpak_output=$(flatpak uninstall --unused -y 2>&1)
        fi

        if [[ "$flatpak_output" == *"Nothing unused to uninstall"* ]]; then
            echo "Keine ungenutzten Flatpaks gefunden."
        else
            echo "$flatpak_output"
        fi
    fi
}

# Funktion: LTS-Kernel-Empfehlung anzeigen
propose_lts() {
    echo -e "\n${gelb}➤ LTS-Kernel-Empfehlung:${reset}"

    # Prüfe, ob installierte Kernel verfügbar sind
    if [ -z "${installed[*]:-}" ]; then
        echo -e "${rot}Keine installierten Kernel erkannt – überspringe Empfehlung.${reset}"
        return
    fi

    # LTS-Liste laden
    if ! mapfile -t lts_list < <(
        curl -fsSL "https://gitlab.manjaro.org/applications/manjaro-settings-manager/-/raw/master/src/libmsm/KernelModel.cpp" |
        awk '/<< "linux.*/ { gsub(/"|;/,"",$NF); print $NF }'
    ); then
        echo -e "${rot}Netzwerkfehler – LTS-Liste nicht geladen.${reset}"
        return
    fi

    if [ "${#lts_list[@]}" -gt 0 ]; then
        echo " → Letzter verfügbarer LTS: ${gruen}${lts_list[0]}${reset}"
        if [ "${#lts_list[@]}" -gt 1 ] && [ "${lts_list[0]}" != "${lts_list[1]}" ]; then
            echo " → Empfohlener LTS laut Manjaro: ${gelb}${lts_list[1]}${reset}"
        fi

        if [[ ! " ${installed[*]} " =~ " ${lts_list[0]} " ]]; then
            echo -e "${gelb}Hinweis:${reset} Der aktuelle LTS-Kernel (${lts_list[0]}) ist ${rot}nicht installiert${reset}."
            echo -e " → Du kannst ihn mit z.B. ${gruen}sudo mhwd-kernel -i ${lts_list[0]}${reset} installieren."
        else
            echo "✓ Empfohlener LTS-Kernel (${lts_list[0]}) ist bereits installiert."
        fi
    else
        echo "${rot}Keine gültige LTS-Liste geladen – keine Empfehlung möglich.${reset}"
    fi
}

while true; do
    clear

    echo "${gruen}"
    echo " __        __   _                            _       "
    echo " \\ \\      / /__| | ___ ___  _ __ ___   ___  | |_ ___ "
    echo "  \\ \\ /\\ / / _ \\ |/ __/ _ \\| '_ \` _ \\ / _ \\ | __/ _ \\"
    echo "   \\ V  V /  __/ | (_| (_) | | | | | |  __/ | || (_) |"
    echo "    \\_/\\_/ \\___|_|\\___\\___/|_| |_| |_|\\___|  \\__\\___/ "
    echo ""
    echo " Linux Manjaro – Systempflege"
    echo " tweaksManjaro.sh ${version}"
    echo " Distro: $distro $manjaro_version"
    echo " Bash: $BASH_VERSION"
    echo "${reset}"

    echo "${gelb}====== Wartungsmenü ======${reset}"
    echo "1) Kernel prüfen und System aktualisieren"
    echo "2) System über AUR aktualisieren (yay)"
    echo "3) Verwaiste Pakete entfernen"
    echo "4) Paket-Caches vollständig löschen"
    echo "5) Spiegelserver für DE/FR/AT aktualisieren"
    echo "6) Zugriffsrechte im Home-Verzeichnis korrigieren"
    echo "7) Systeminformationen anzeigen"
    echo "8) Fehler seit letztem Boot (journalctl)"
    echo "9) Temperatur-Sensorwerte anzeigen"
    echo "10) NVMe S.M.A.R.T.-Status anzeigen"
    echo "11) USB S.M.A.R.T.-Status anzeigen"
    echo "12) Pacman-Datenbanksperre entfernen"
    echo "13) fstrim auf SSDs ausführen"
    echo "14) Speicherplatz anzeigen (Zurück mit Taste Q)"
    echo "15) Systemmonitor htop starten (Zurück F10)"
    echo "16) Btrfs-Datenprüfung (scrub) – kann dauern"
    echo "17) Btrfs-Prüfstatus anzeigen"
    echo "0) Beenden"
    echo ""
    read -r -p "Auswahl [0-17]: " answer
    [ "${LOGGING:-}" = "true" ] && log_msg "MENU: Auswahl=${answer}"
case "$answer" in
            1)
            CURRENT_STEP_NAME="Punkt 1 - Kernel prüfen und System aktualisieren"
            log_start "$CURRENT_STEP_NAME"
            # Kernel Check & Systemaktualisierung
            echo -e "\n${gelb}➤ Kernelprüfung und Systemaktualisierung gestartet...${reset}"

            # EOL-Liste laden
            if ! mapfile -t eol_list < <(
                curl -fsSL "https://forum.manjaro.org/c/announcements/${branch}-updates.rss" |
                awk -F'>| ' '/\[EOL\]/ {print $2}' | sort -u
            ); then
                echo -e "${rot}Netzwerkfehler beim Laden der EOL-Liste – überspringe EOL-Check.${reset}"
                eol_list=()
            fi

            # installierte Kernel ermitteln
            mapfile -t installed < <(mhwd-kernel -li | awk '{print $2}' | grep '^linux')
            echo -e "\n${gelb}➤ Installierte Kernel prüfen:${reset}"
            eol_warning=0
            for k in "${installed[@]}"; do
                if printf "%s\n" "${eol_list[@]}" | grep -qx "$k"; then
                    echo -e " → ${rot}Kernel $k ist EOL${reset}"
                    eol_warning=1
                else
                    echo -e " → ${gruen}Kernel $k ist OK${reset}"
                fi
            done

            if [ "$eol_warning" -gt 0 ]; then
                echo -e "\n${rot}⚠️  Mindestens ein installierter Kernel ist veraltet (EOL).${reset}"
            else
                echo -e "\n${gruen}✅ Alle installierten Kernel sind aktuell.${reset}"
            fi

            propose_lts

            echo -e "\n${gelb}➤ Systemaktualisierung läuft, STRG+C ist deaktiviert...${reset}"

            # Führt eine vollständige Systemaktualisierung durch:
            # - Syy: Erzwingt das Neuladen aller Paketdatenbanken
            # - uu: Führt zusätzlich auch Downgrades durch, wenn eine ältere Version im Repo liegt
            # → Sinnvoll bei Branch-Wechseln oder zur Behebung von Paketinkonsistenzen
            # Hinweis: Für normale Updates genügt in der Regel "sudo pacman -Syu"

            # Führt eine vollständige Systemaktualisierung durch:
            # Fragt interaktiv, ob mit -Syu (Standard) oder -Syyuu aktualisiert werden soll
            read -rp "Standard-Synchronisation (-Syu) [J] oder vollständig (-Syyuu) [n]? (Standard: J): " choice
            if [[ "$choice" =~ ^[Jj]$ ]]; then
                run_soft_logged sudo pacman --color=never -Syu
            else
                run_soft_logged sudo pacman --color=never -Syyuu
            fi

            # Entfernt alle bis auf die zwei zuletzt installierten Versionen jedes Pakets aus dem Cache
            # → Spart Speicherplatz, behält aber zwei Versionen für eventuelle Rollbacks
            if command -v paccache &>/dev/null; then
                sudo paccache -rk2
            else
                echo "Hinweis: paccache nicht gefunden."
            fi

            echo -e "\n${gelb}➤ Verwaiste Pakete:${reset}"
            orphans=$(sudo pacman -Qdtq || true)
            if [ -z "$orphans" ]; then
                echo "${gruen}Keine verwaisten Pakete gefunden.${reset}"
            else
                echo "$orphans"
            fi

            update_flatpak
            update_grub
            press_enter
            ec=$?
            log_end "$CURRENT_STEP_NAME" "$ec"
            unset CURRENT_STEP_NAME
            ;;
        2)
            CURRENT_STEP_NAME="Punkt 2 - System über AUR aktualisieren (yay)"
            log_start "$CURRENT_STEP_NAME"
            # AUR Systemaktualisierung (yay)
            echo -e "\n${gelb}➤ AUR Systemaktualisierung gestartet...${reset}"

            if ! command -v yay &>/dev/null; then
                echo -e "${rot}Fehler: yay ist nicht installiert!${reset}"
                echo -e " → Bitte zuerst mit: ${gruen}sudo pacman -S yay${reset}"
                press_enter
                break
            fi

            echo -e "\n${gelb}➤ Offizielle Repos synchronisieren...${reset}"
            sudo pacman -Syy

            echo -e "\n${gelb}➤ AUR und Repo-Pakete aktualisieren, STRG+C ist deaktiviert...${reset}"

            # Führt eine vollständige Systemaktualisierung durch:
            # - Syy: Erzwingt das Neuladen aller Paketdatenbanken
            # - uu: Führt zusätzlich auch Downgrades durch, wenn eine ältere Version im Repo oder in der AUR vorliegt
            # → Sinnvoll bei Branch-Wechseln oder zur Behebung von Paketinkonsistenzen
            # Hinweis: Für normale Updates genügt in der Regel "yay -Syu"

            # Führt eine vollständige Systemaktualisierung durch:
            # Fragt interaktiv, ob mit -Syu (Standard) oder -Syyuu aktualisiert werden soll
            read -rp "Standard-Synchronisation (-Syu) [J] oder vollständig (-Syyuu) [n]? (Standard: J): " choice
            if [[ "$choice" =~ ^[Jj]$ ]]; then
                run_soft_logged yay --color=never -Syu
            else
                run_soft_logged yay --color=never -Syyuu
            fi

            # Entfernt alle bis auf die zwei zuletzt installierten Versionen jedes Pakets aus dem Cache
            # → Spart Speicherplatz, behält aber zwei Versionen für eventuelle Rollbacks
            if command -v paccache &>/dev/null; then
                sudo paccache -rk2
            else
                echo "Hinweis: paccache nicht gefunden."
            fi

            echo -e "\n${gelb}➤ Verwaiste Pakete:${reset}"
            orphans=$(sudo pacman -Qdtq || true)
            if [ -z "$orphans" ]; then
                echo "${gruen}Keine verwaisten Pakete gefunden.${reset}"
            else
                echo "$orphans"
            fi

            update_flatpak
            update_grub
            press_enter
            ec=$?
            log_end "$CURRENT_STEP_NAME" "$ec"
            unset CURRENT_STEP_NAME
            ;;
        3)
            CURRENT_STEP_NAME="Punkt 3 - Verwaiste Pakete entfernen"
            log_start "$CURRENT_STEP_NAME"
            # Verwaiste Pakete löschen
            mapfile -t orphans < <(pacman -Qdtq)
            if [ ${#orphans[@]} -gt 0 ]; then
                if [ "${LOGGING:-}" = "true" ]; then
                    {
                        echo "ORPHANS_BEFORE (${#orphans[@]}):"
                        printf '%s\n' "${orphans[@]}"
                    } >> "${LOG_FILE}"
                fi
                run_soft_logged sudo pacman --color=never -Rsn "${orphans[@]}"
            else
                echo "Keine verwaisten Pakete gefunden."
            fi
            press_enter
            ec=$?
            log_end "$CURRENT_STEP_NAME" "$ec"
            unset CURRENT_STEP_NAME
            ;;
        4)
            CURRENT_STEP_NAME="Punkt 4 - Paket-Caches vollständig löschen"
            log_start "$CURRENT_STEP_NAME"
            # Alle Caches löschen
            echo -e "\n${gelb}➤ Alle Caches löschen (pacman + yay):${reset}"
            echo "(Mehrere Rückfragen möglich – bewusst bestätigen!)"

            # Aufräumaktion: temporäre Download-Verzeichnisse löschen
            # Beispiel: Wenn die Meldung erscheint –
            # "Fehler: /var/cache/pacman/download-pZbyXs konnte nicht entfernt werden: Ist ein Verzeichnis"
            read -r -p "➤ Temporäre download-* Verzeichnisse löschen? [j/N]: " confirm
            if [[ "$confirm" =~ ^[Jj]$ ]]; then
                echo "→ download-* Verzeichnisse aufräumen..."
                sudo find /var/cache/pacman/pkg -type d -name 'download-*' -exec rm -r {} +
            fi

           # Löscht alle zwischengespeicherten Pakete vollständig (Cache vollständig leeren)
           # → Achtung: Nach dem Löschen müssen alle Pakete bei Bedarf neu aus dem Internet geladen werden
           # yay -Scc: für Systeme mit AUR-Unterstützung (yay installiert)
           # pacman -Scc: Standard für Systeme ohne yay
            if command -v yay &>/dev/null; then
                yay -Scc
            else
                sudo pacman -Scc
            fi

            press_enter
            ec=$?
            log_end "$CURRENT_STEP_NAME" "$ec"
            unset CURRENT_STEP_NAME
            ;;
        5)
            CURRENT_STEP_NAME="Punkt 5 - Spiegelserver für DE/FR/AT aktualisieren"
            log_start "$CURRENT_STEP_NAME"
            # Spiegelserver aus DE/FR/AT optimieren
            echo -e "\nSpiegelserver D/F/Ö aktualisieren:\n"
            sudo pacman-mirrors --country Germany,France,Austria
            press_enter
            ec=$?
            log_end "$CURRENT_STEP_NAME" "$ec"
            unset CURRENT_STEP_NAME
            ;;
        6)
            CURRENT_STEP_NAME="Punkt 6 - Zugriffsrechte im Home-Verzeichnis korrigieren"
            log_start "$CURRENT_STEP_NAME"
            # Zugriffsrechte aktualisieren
            echo -e "\nZugriffsrechte neu setzen:\n"

            echo "→ Besitzerrechte im Home-Verzeichnis setzen..."
            sudo chown -R "$USER:$USER" "$HOME"

            if [ "$zugriffsrechte" -gt 0 ]; then
                echo "→ Standardrechte setzen (Verzeichnisse 755, Dateien 644, Home 711 für Apache-Zugriff)..."
                sudo find "$HOME" -type d -exec chmod 755 {} +
                sudo find "$HOME" -type f -exec chmod 644 {} +
                chmod 711 "$HOME"

                if [ -d "$HOME/.gnupg" ]; then
                    echo "→ Spezielle Rechte für .gnupg anwenden..."
                    sudo find "$HOME/.gnupg" -type d -exec chmod 700 {} +
                    sudo find "$HOME/.gnupg" -type f -exec chmod 600 {} +
                fi

                if [ -d "$HOME/.ssh" ]; then
                    echo "→ Rechte für .ssh setzen..."
                    sudo chmod 700 "$HOME/.ssh"
                    sudo find "$HOME/.ssh" -type f -name "id_*" ! -name "*.pub" -exec chmod 600 {} +
                    sudo find "$HOME/.ssh" -type f -name "*.pub" -exec chmod 644 {} +
                    [ -f "$HOME/.ssh/authorized_keys" ] && sudo chmod 600 "$HOME/.ssh/authorized_keys"
                    [ -f "$HOME/.ssh/config" ] && sudo chmod 600 "$HOME/.ssh/config"
                    [ -f "$HOME/.ssh/known_hosts" ] && sudo chmod 644 "$HOME/.ssh/known_hosts"
                    echo "Hinweis: Rechte für .ssh angepasst."
                fi

                if [ -d "$HOME/.aws" ]; then
                    echo "→ Rechte für .aws setzen..."
                    sudo chmod 700 "$HOME/.aws"
                    for awsfile in "$HOME/.aws/config" "$HOME/.aws/credentials"; do
                        if [ -f "$awsfile" ]; then
                            sudo chmod 600 "$awsfile"
                            echo "Hinweis: Rechte für $awsfile auf 600 gesetzt."
                        fi
                    done
                fi

                echo "→ Rechte für sensible Dateien (.env, .secrets etc.) setzen..."
                for file in "$HOME/.env" "$HOME/.vps-env" "$HOME/.secrets" "$HOME/.netrc" "$HOME/.pypirc" "$HOME/.git-credentials"; do
                    if [ -f "$file" ]; then
                        sudo chmod 600 "$file"
                        echo "Hinweis: Rechte für $file auf 600 gesetzt."
                    fi
                done
            fi

            if [ "$html" -eq 1 ]; then
                echo "→ Rechte für public_html setzen (Home 711 für Apache-Zugriff)..."
                chmod 711 "$HOME"
                sudo chown -R http:http "$HOME/public_html"
                sudo find "$HOME/public_html" -type d -exec chmod 2775 {} +
                sudo find "$HOME/public_html" -type f -exec chmod 0664 {} +
            fi

            echo "→ Setze Ausführbarkeit für *.sh, *.desktop und *.AppImage..."
            sudo find "$HOME" -name "*.sh" -exec chmod 0744 {} +
            sudo find "$HOME" -name "*.desktop" -exec chmod 0744 {} +
            sudo find "$HOME" -name "*.AppImage" -exec chmod 0744 {} +

            echo -e "\n✅ Alle Berechtigungen wurden gesetzt."
            press_enter
            ec=$?
            log_end "$CURRENT_STEP_NAME" "$ec"
            unset CURRENT_STEP_NAME
            ;;
        7)
            CURRENT_STEP_NAME="Punkt 7 - Systeminformationen anzeigen"
            log_start "$CURRENT_STEP_NAME"
            # Systeminformationen anzeigen
            echo -e "\nSysteminformationen:\n"
            if command -v lsb_release &>/dev/null; then
               lsb_release -a
            else
               echo "lsb_release nicht gefunden."
            fi

            if command -v inxi &>/dev/null; then
                inxi -Fz
            else
                echo "inxi nicht gefunden."
            fi
            press_enter
            ec=$?
            log_end "$CURRENT_STEP_NAME" "$ec"
            unset CURRENT_STEP_NAME
            ;;
        8)
            CURRENT_STEP_NAME="Punkt 8 - Fehler/Kritisch seit letztem Boot (journalctl)"
            log_start "$CURRENT_STEP_NAME"

            echo -e "\n${gelb}➤ Fehler/Kritisch seit letztem Boot (journalctl -b -p 3 --no-pager):${reset}"
            if command -v journalctl >/dev/null 2>&1; then
                # Erst ohne sudo versuchen (reicht i. d. R.),
                # bei Fehler (z. B. wegen Rechten) fallback mit sudo.
                if ! journalctl -b -p 3 --no-pager; then
                    echo -e "\n${gelb}Hinweis:${reset} erneuter Versuch mit sudo…"
                    sudo journalctl -b -p 3 --no-pager || true
                fi
            else
                echo -e "${rot}journalctl nicht gefunden – System ohne systemd oder Tool fehlt.${reset}"
            fi

            press_enter
            ec=$?
            log_end "$CURRENT_STEP_NAME" "$ec"
            unset CURRENT_STEP_NAME
            ;;
        9)
            CURRENT_STEP_NAME="Punkt 9 - Temperatur-Sensorwerte anzeigen"
            log_start "$CURRENT_STEP_NAME"
            # Temperatursensoren ausgeben
            echo -e "\nTemperatursensoren:\n"
            if command -v sensors &>/dev/null; then
                sensors
            else
                echo "sensors nicht gefunden."
            fi
            press_enter
            ec=$?
            log_end "$CURRENT_STEP_NAME" "$ec"
            unset CURRENT_STEP_NAME
            ;;
        10)
            CURRENT_STEP_NAME="Punkt 10 - NVMe S.M.A.R.T.-Status anzeigen"
            log_start "$CURRENT_STEP_NAME"
            echo -e "\nNVMe SSD S.M.A.R.T. LOG:\n"

            if ! command -v nvme >/dev/null 2>&1; then
                echo "${rot}nvme-cli ist nicht installiert. Bitte 'nvme-cli' nachinstallieren.${reset}"
            else
                nvmes=$(ls /dev/nvme[0-9] 2>/dev/null || true)  # nur Controller: /dev/nvme0, /dev/nvme1, ...

                # Jeder gefundene Controller wird einzeln mit nvme smart-log geprüft.
                # Namespaces und Partitionen (z.B. /dev/nvme0n1, /dev/nvme0n1p1) werden bewusst ausgelassen,
                # um doppelte oder unübersichtliche Ausgaben zu vermeiden.

                if [ -z "$nvmes" ]; then
                    echo "${rot}Keine NVMe-SSD gefunden.${reset}"
                else
                    for dev in $nvmes; do
                        echo "${gruen}S.M.A.R.T.-Log für $dev:${reset}"
                        if ! sudo nvme smart-log "$dev"; then
                            echo "${rot}Fehler: Kein Zugriff auf $dev oder Befehl nicht unterstützt.${reset}"
                        fi
                        echo ""
                        echo "---------------------------------------------"
                    done
                fi
            fi

            press_enter
            ec=$?
            log_end "$CURRENT_STEP_NAME" "$ec"
            unset CURRENT_STEP_NAME
            ;;
        11)
            CURRENT_STEP_NAME="Punkt 11 - USB S.M.A.R.T.-Status anzeigen"
            log_start "$CURRENT_STEP_NAME"

            if ! command -v smartctl >/dev/null 2>&1; then
                echo "${rot}smartmontools ist nicht installiert. Bitte 'smartmontools' nachinstallieren.${reset}"
            else
                echo "${blau}Suche nach USB-Laufwerken...${reset}"
                usb_devs=$(lsblk -d -o NAME,TRAN | awk '$2=="usb"{print $1}')

                if [ -z "$usb_devs" ]; then
                    echo "${rot}Keine USB-Laufwerke gefunden.${reset}"
                else
                    for dev in $usb_devs; do
                        echo "${blau}Prüfe /dev/$dev ...${reset}"

                        # Versuchskette: normal → -d sat → -d scsi → -T permissive
                        # Hintergrund: Manche USB-Adapter leiten SMART nur mit bestimmten Treiber-Optionen durch.
                        # Mit -T permissive werden notfalls eingeschränkte Infos angezeigt.

                        if ! sudo smartctl -a /dev/$dev; then
                            if ! sudo smartctl -a -d sat /dev/$dev; then
                                if ! sudo smartctl -a -d scsi /dev/$dev; then
                                    sudo smartctl -a -T permissive /dev/$dev
                                fi
                            fi
                        fi

                        echo "---------------------------------------------"
                    done
                fi
            fi

            press_enter
            ec=$?
            log_end "$CURRENT_STEP_NAME" "$ec"
            unset CURRENT_STEP_NAME
            ;;
        12)
            CURRENT_STEP_NAME="Punkt 11 - Pacman-Datenbanksperre entfernen"
            log_start "$CURRENT_STEP_NAME"
            # Datenbanksperre löschen
            echo -e "\nDatenbanksperre löschen:\n"
            if [ -f /var/lib/pacman/db.lck ]; then
                sudo rm -f /var/lib/pacman/db.lck
            else
                echo "Keine Datenbanksperre gefunden."
            fi
            press_enter
            ec=$?
            log_end "$CURRENT_STEP_NAME" "$ec"
            unset CURRENT_STEP_NAME
            ;;
        13)
            CURRENT_STEP_NAME="Punkt 12 - fstrim auf SSDs ausführen"
            log_start "$CURRENT_STEP_NAME"
            # fstrim ausführen
            echo -e "\nfstrim auf SSDs:\n"
            if command -v fstrim &>/dev/null; then
                sudo fstrim -av
            else
                echo "${rot}fstrim ist nicht installiert.${reset}"
            fi
            press_enter
            ec=$?
            log_end "$CURRENT_STEP_NAME" "$ec"
            unset CURRENT_STEP_NAME
            ;;
        14)
            CURRENT_STEP_NAME="Punkt 13 - Speicherplatz anzeigen (Zurück mit Taste Q)"
            log_start "$CURRENT_STEP_NAME"
            # Speicherplatz anzeigen (df -h)
            echo -e "\n${gelb}➤ Speicherplatz anzeigen (df -h)...${reset}"
            df -h | less
            press_enter
            ec=$?
            log_end "$CURRENT_STEP_NAME" "$ec"
            unset CURRENT_STEP_NAME
            ;;
        15)
            CURRENT_STEP_NAME="Punkt 14 - Systemmonitor htop starten (Zurück F10)"
            log_start "$CURRENT_STEP_NAME"
            # htop starten
            echo -e "\n${gelb}➤ Starte htop...${reset}"
            if command -v htop &>/dev/null; then
                htop
            else
                echo -e "${rot}htop ist nicht installiert.${reset}"
            fi
            press_enter
            ec=$?
            log_end "$CURRENT_STEP_NAME" "$ec"
            unset CURRENT_STEP_NAME
            ;;
        16)
            CURRENT_STEP_NAME="Punkt 15 - Btrfs-Datenprüfung (scrub) – kann dauern"
            log_start "$CURRENT_STEP_NAME"
            # Btrfs-Datenprüfung (scrub)
            echo "${blau}Starte Btrfs scrub – kann einige Zeit dauern...${reset}"
            sudo btrfs scrub start -Bd /
            press_enter
            ec=$?
            log_end "$CURRENT_STEP_NAME" "$ec"
            unset CURRENT_STEP_NAME
            ;;
        17)
            CURRENT_STEP_NAME="Punkt 16 - Btrfs-Prüfstatus anzeigen"
            log_start "$CURRENT_STEP_NAME"
            # Btrfs-Prüfstatus anzeigen
            echo "${blau}Btrfs scrub Status:${reset}"
            sudo btrfs scrub status /
            press_enter
            ec=$?
            log_end "$CURRENT_STEP_NAME" "$ec"
            unset CURRENT_STEP_NAME
            ;;

        0)
            echo "${gruen}Skript wird beendet.${reset}"
            exit 0
            ;;
        *)
            echo "${rot}Ungültige Auswahl.${reset}"
            press_enter
            ;;
    esac
done