#!/bin/bash # === PVE Kernel Cleaner Script === # Kompatibel mit EFI & BIOS, erkennt ZFS Pools und prüft Belegung # Erkennt auch Subscription-Status # Autor: Patrick Perlbach # Datum: 2025-06-20 # Farben & Formatierung bold=$(tput bold) reset=$(tput sgr0) green=$(tput setaf 2) yellow=$(tput setaf 3) red=$(tput setaf 1) # Einstellungen ZFS_DATASET="rpool/ROOT/pve-1" # ZFS Dataset für Boot-Pool SNAPSHOT_TAG="pve-kernel-cleaner" # Tag für Snapshots MAX_SNAPSHOTS=5 # Max. Snapshots behalten LOGFILE="/var/log/pve-kernel-cleaner.log" # Logdatei TIMESTAMP=$(date +%Y-%m-%d-%H-%M-%S) # Zeitstempel für Snapshots dry_run="false" # Standard: kein Testlauf # Hilfe anzeigen show_help() { cat << EOF Verwendung: $(basename "$0") [OPTIONEN] Dieses Script entfernt alte Proxmox Kernel und behält eine definierte Anzahl neuer Kernel. Optionen: -k NUM Anzahl der Kernel, die behalten werden sollen (Standard: 1) -d Testmodus (Dry-Run), keine Änderungen werden vorgenommen -h Diese Hilfe anzeigen EOF } # Systeminformationen anzeigen kernel_info() { echo "=== PVE Kernel Cleaner Script ===" echo "" echo "Systeminformationen:" echo "─────────────────────────────" current_kernel=$(uname -r) kernels_installed=($(dpkg --list | awk '/proxmox-kernel-.*-pve-signed/ {print $2}' | sort -V)) num_kernels=${#kernels_installed[@]} if [ -d /sys/firmware/efi ]; then echo "Boot-Modus: EFI" else echo "Boot-Modus: Legacy (BIOS)" fi if [ -f /etc/os-release ]; then os_name=$(grep PRETTY_NAME /etc/os-release | cut -d= -f2 | tr -d '"') echo "Betriebssystem: $os_name" fi if zfs list $ZFS_DATASET &>/dev/null; then boot_used=$(zfs get -H -o value used $ZFS_DATASET) boot_avail=$(zfs get -H -o value available $ZFS_DATASET) echo "ZFS Boot-Pool ($ZFS_DATASET): benutzt $boot_used, verfügbar $boot_avail" else boot_df=($(df -h /boot | tail -1)) echo "Boot-Partition: ${boot_df[2]} verwendet von ${boot_df[1]} verfügbar (${boot_df[4]} voll)" fi echo "Aktueller Kernel: $current_kernel" echo "Installierte Proxmox-Kernel ($num_kernels):" for k in "${kernels_installed[@]}"; do echo " - $k" done echo "─────────────────────────────" echo "" } # Prüfe Subscription-Status der APT-Repositories check_apt_repos() { echo "APT-Repositories:" repo_files=$(find /etc/apt/ -name "*.list") if grep -rq "enterprise.proxmox.com" $repo_files; then echo "PVE Enterprise Repository (Subscription) ist aktiv" elif grep -rq "no-subscription" $repo_files; then echo "PVE No-Subscription Repository ist aktiv" else echo "Kein bekanntes PVE Repository aktiv, prüfe apt-Sources manuell" fi echo "" } # Snapshot erstellen, falls ZFS vorhanden create_snapshot() { if zfs list $ZFS_DATASET &>/dev/null; then snapshot_name="${ZFS_DATASET}@${SNAPSHOT_TAG}-${TIMESTAMP}" echo "Erstelle ZFS Snapshot: $snapshot_name" if [ "$dry_run" = "false" ]; then zfs snapshot "$snapshot_name" || echo "${red}Snapshot konnte nicht erstellt werden!${reset}" else echo "Snapshot würde erstellt: $snapshot_name" fi fi } # Alte Snapshots löschen, wenn zu viele vorhanden sind cleanup_snapshots() { if zfs list $ZFS_DATASET &>/dev/null; then snapshots=($(zfs list -t snapshot -o name -s creation | grep "$SNAPSHOT_TAG" | grep "^${ZFS_DATASET}@${SNAPSHOT_TAG}" || true)) num_snapshots=${#snapshots[@]} if (( num_snapshots > MAX_SNAPSHOTS )); then delete_count=$((num_snapshots - MAX_SNAPSHOTS)) echo "Es sind $num_snapshots Snapshots mit Tag '$SNAPSHOT_TAG' vorhanden. Entferne $delete_count alte Snapshot(s)." for ((i=0; i /dev/null 2>&1 if [ $? -eq 0 ]; then printf "${green}Fertig!${reset}\n" else printf "${red}Fehler!${reset}\n" fi else echo "Kernel würde entfernt: $k" fi done # Grub aktualisieren printf "${bold}[*]${reset} Aktualisiere GRUB... " if [ "$dry_run" = "false" ]; then if command -v proxmox-boot-tool >/dev/null 2>&1; then proxmox-boot-tool refresh > /dev/null 2>&1 else update-grub > /dev/null 2>&1 fi printf "${green}Fertig!${reset}\n" else echo "GRUB würde aktualisiert werden." fi # Alte Snapshots bereinigen cleanup_snapshots } main() { local keep=1 # Optionen parsen while getopts ":k:dh" opt; do case $opt in k) keep=$OPTARG ;; d) dry_run="true" ;; h) show_help; exit 0 ;; \?) echo "Ungültige Option: -$OPTARG" >&2; show_help; exit 1 ;; :) echo "Option -$OPTARG benötigt ein Argument." >&2; show_help; exit 1 ;; esac done kernel_info check_apt_repos echo "[-] PVE kernel search complete!" echo "" # Kernel-Keeping abfragen read -rp "Wie viele Kernel sollen behalten werden? [Standard: $keep]: " user_keep if [[ "$user_keep" =~ ^[0-9]+$ ]]; then keep=$user_keep fi remove_old_kernels "$keep" # Anzahl Snapshots am Ende anzeigen if zfs list $ZFS_DATASET &>/dev/null; then snapshots=($(zfs list -t snapshot -o name -s creation | grep "$SNAPSHOT_TAG" | grep "^${ZFS_DATASET}@${SNAPSHOT_TAG}" || true)) num_snapshots=${#snapshots[@]} echo "" echo "Anzahl vorhandener Snapshots mit Tag '$SNAPSHOT_TAG': $num_snapshots" fi echo "" echo "Fertig." } main "$@"