#!/usr/bin/env bash # Beschreibung: Führt fstrim in LXC-Containern auf einem Proxmox-Host aus # Aufrufbeispiele: # ./fstrim-lxc.sh --all #Alle LXCs # ./fstrim-lxc.sh -i 102,103 #Gewünschte IDs # ./fstrim-lxc.sh #Interaktiver Modus mit Auswahlmenü # Synapse: https://git.techniverse.net/scriptos/fstrim-lxc.git # Autor: Patrick Asmus # Web: https://www.cleveradmin.de # Version: 1.0 # Datum: 31.10.2025 # Modifikation: Initial ##################################################### set -euo pipefail # --- Einstellungen --- DEFAULT_TIMEOUT=60 # Sekunden; je pct fstrim-Aufruf # --------------------- log() { echo "[$(date +'%F %T')] $*"; } have() { command -v "$1" >/dev/null 2>&1; } usage() { cat <<'EOF' Verwendung: fstrim-lxc.v1.sh -all [--timeout SECONDS] -> pct fstrim auf allen laufenden LXC-Containern ausführen fstrim-lxc.v1.sh -i 102,103 [--timeout SECONDS] fstrim-lxc.v1.sh -102,103 [--timeout SECONDS] -> pct fstrim nur auf diesen IDs ausführen fstrim-lxc.v1.sh -> Interaktives Menü Optionen: --timeout N : Timeout pro Container (Sekunden), Default 60 -h | --help : Hilfe Hinweise: - Gestoppte Container werden übersprungen (kein Auto-Start). - Benötigt root und das Proxmox-Tool "pct". EOF } require_root() { if [[ $EUID -ne 0 ]]; then echo "Bitte als root ausführen." >&2 exit 1 fi } list_all_ids() { pct list | awk 'NR>1 {print $1}' } exists_id() { local id="$1" list_all_ids | grep -qx "$id" } is_running() { local id="$1" pct status "$id" 2>/dev/null | grep -q "status: running" } do_fstrim() { local id="$1" local timeout_s="$2" if ! exists_id "$id"; then log "[ID $id] existiert nicht. Übersprungen." return 1 fi if ! is_running "$id"; then log "[ID $id] gestoppt. Übersprungen (kein Auto-Start)." return 2 fi if ! have pct; then log "Fehler: pct nicht gefunden." return 3 fi log "[ID $id] pct fstrim (Timeout ${timeout_s}s)..." if timeout "$timeout_s" pct fstrim "$id"; then log "[ID $id] OK." return 0 else log "[ID $id] Fehler oder Timeout." return 4 fi } run_for_ids() { local ids_csv="$1" local timeout_s="$2" ids_csv="${ids_csv//[[:space:]]/}" IFS=',' read -r -a ids <<< "$ids_csv" [[ ${#ids[@]} -gt 0 ]] || { echo "Keine gültigen IDs."; exit 1; } local rc=0 for id in "${ids[@]}"; do if [[ ! "$id" =~ ^[0-9]+$ ]]; then log "[$id] keine numerische ID. Übersprungen." rc=1 continue fi do_fstrim "$id" "$timeout_s" || rc=1 done return $rc } run_for_all() { local timeout_s="$1" mapfile -t all_ids < <(list_all_ids) if [[ ${#all_ids[@]} -eq 0 ]]; then log "Keine LXC-Container gefunden." return 0 fi log "Starte pct fstrim für alle laufenden Container: ${all_ids[*]}" local rc=0 for id in "${all_ids[@]}"; do do_fstrim "$id" "$timeout_s" || rc=1 done return $rc } interactive_menu() { echo "Kein Parameter übergeben. Bitte auswählen:" echo " 1) Alle laufenden LXC-Container trimmen" echo " 2) Bestimmte IDs (kommagetrennt)" read -r -p "Auswahl [1/2]: " choice case "$choice" in 1) run_for_all "$TIMEOUT_S" ;; 2) read -r -p "IDs (z. B. 102,103): " ids run_for_ids "$ids" "$TIMEOUT_S" ;; *) echo "Ungültige Auswahl."; exit 1 ;; esac } # --- Main --- require_root have pct || { echo "Fehler: 'pct' nicht verfügbar. Bitte auf einem Proxmox-Host ausführen."; exit 1; } TIMEOUT_S=$DEFAULT_TIMEOUT # globale Option --timeout vorziehen while [[ $# -gt 1 ]]; do case "$1" in --timeout) TIMEOUT_S="${2:-$DEFAULT_TIMEOUT}"; shift 2 ;; *) break ;; esac done if [[ $# -eq 0 ]]; then interactive_menu exit $? fi case "$1" in -h|--help) usage; exit 0 ;; -all|--all) run_for_all "$TIMEOUT_S"; exit $? ;; -i|--ids) [[ -z "${2:-}" ]] && { echo "Fehler: IDs fehlen, z. B. -i 101,102"; exit 1; } run_for_ids "$2" "$TIMEOUT_S"; exit $? ;; -[0-9]*) ids_arg="${1#-}" run_for_ids "$ids_arg" "$TIMEOUT_S"; exit $? ;; *) echo "Unbekannter Parameter: $1" usage exit 1 ;; esac