pve-kernel-cleaner.sh aktualisiert

This commit is contained in:
2025-06-21 01:29:03 +02:00
parent ca48da86b3
commit 3048a2ab6a
+214 -71
View File
@@ -6,88 +6,231 @@
# Autor: Patrick Perlbach # Autor: Patrick Perlbach
# Datum: 2025-06-20 # Datum: 2025-06-20
set -e # Farben & Formatierung
bold=$(tput bold)
reset=$(tput sgr0)
green=$(tput setaf 2)
yellow=$(tput setaf 3)
red=$(tput setaf 1)
echo "==== PVE Kernel Cleaner ====" # Einstellungen
echo "" 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
# 1. Prüfen ob EFI oder BIOS # Hilfe anzeigen
if [ -d /sys/firmware/efi ]; then show_help() {
echo "Bootmodus: EFI" cat << EOF
else Verwendung: $(basename "$0") [OPTIONEN]
echo "Bootmodus: BIOS (Legacy)"
fi
# 1.1 Subscription-Status prüfen Dieses Script entfernt alte Proxmox Kernel und behält eine definierte Anzahl neuer Kernel.
echo ""
echo "APT-Repositories:"
repo_files=$(find /etc/apt/ -name "*.list")
if grep -rq "enterprise.proxmox.com" $repo_files; then Optionen:
echo "PVE Enterprise Repository (Subscription) ist aktiv" -k NUM Anzahl der Kernel, die behalten werden sollen (Standard: 1)
elif grep -rq "no-subscription" $repo_files; then -d Testmodus (Dry-Run), keine Änderungen werden vorgenommen
echo "PVE No-Subscription Repository ist aktiv" -h Diese Hilfe anzeigen
else EOF
echo "Kein bekanntes PVE Repository aktiv, prüfe apt-Sources manuell" }
fi
echo "" # Systeminformationen anzeigen
kernel_info() {
echo "=== PVE Kernel Cleaner Script ==="
echo ""
echo "Systeminformationen:"
echo "─────────────────────────────"
# 2. ZFS Pools prüfen current_kernel=$(uname -r)
echo "ZFS Pool Übersicht:" kernels_installed=($(dpkg --list | awk '/proxmox-kernel-.*-pve-signed/ {print $2}' | sort -V))
if command -v zpool &> /dev/null; then num_kernels=${#kernels_installed[@]}
zpool list -Ho name,capacity | while read -r pool cap; do
cap_num=$(echo $cap | tr -d '%')
warn=""
if (( cap_num >= 80 )); then
warn="ACHTUNG: >80% belegt"
fi
echo "$pool: $cap $warn"
done
else
echo "ZFS ist nicht installiert oder zpool-Befehl nicht verfügbar."
fi
echo "" if [ -d /sys/firmware/efi ]; then
echo "Boot-Modus: EFI"
# 3. Liste der installierten PVE-Kernel anzeigen und alte Kernel identifizieren
echo "Installierte PVE-Kernel:"
kernel_list=$(dpkg --list | grep pve-kernel | awk '{print $2}' | sort -V)
current_kernel=$(uname -r | cut -d '-' -f1-2)
to_remove=()
while read -r kernel; do
version=$(echo "$kernel" | sed -n 's/^pve-kernel-\([0-9.]*-[0-9]*\).*/\1/p')
if [ "$version" == "$current_kernel" ]; then
echo " * $kernel (aktuell in Verwendung)"
else else
echo " - $kernel (alt)" echo "Boot-Modus: Legacy (BIOS)"
to_remove+=("$kernel")
fi fi
done <<< "$kernel_list"
echo "" if [ -f /etc/os-release ]; then
if [ ${#to_remove[@]} -eq 0 ]; then os_name=$(grep PRETTY_NAME /etc/os-release | cut -d= -f2 | tr -d '"')
echo "Keine alten Kernel gefunden, nichts zu tun." echo "Betriebssystem: $os_name"
exit 0 fi
fi
# 4. Nutzerabfrage zur Entfernung if zfs list $ZFS_DATASET &>/dev/null; then
echo "Die folgenden alten Kernel könnten entfernt werden:" boot_used=$(zfs get -H -o value used $ZFS_DATASET)
for k in "${to_remove[@]}"; do 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" echo " - $k"
done done
echo "─────────────────────────────"
echo ""
}
echo "" # Prüfe Subscription-Status der APT-Repositories
read -p "Möchtest du diese alten Kernel jetzt entfernen? (j/n): " confirm check_apt_repos() {
if [[ "$confirm" =~ ^[Jj]$ ]]; then echo "APT-Repositories:"
echo "Entferne alte Kernel..." repo_files=$(find /etc/apt/ -name "*.list")
apt remove --purge -y "${to_remove[@]}"
echo "Alte Kernel wurden entfernt."
else
echo "Abbruch, keine Kernel wurden entfernt."
fi
echo "" if grep -rq "enterprise.proxmox.com" $repo_files; then
echo "==== Fertig ====" 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<delete_count; i++)); do
snap_to_delete=${snapshots[i]}
echo "Lösche Snapshot: $snap_to_delete"
if [ "$dry_run" = "false" ]; then
zfs destroy "$snap_to_delete" || echo "${red}Snapshot $snap_to_delete konnte nicht gelöscht werden!${reset}"
else
echo "Snapshot würde gelöscht: $snap_to_delete"
fi
done
fi
fi
}
# Alte Kernel entfernen
remove_old_kernels() {
local keep=$1
echo "Es werden alle außer den $keep neuesten Kernel entfernt..."
# Nur pve-signed Kernel-Pakete auflisten, sortiert
mapfile -t kernels < <(dpkg --list | awk '/proxmox-kernel-.*-pve-signed/ {print $2}' | sort -V)
local total=${#kernels[@]}
echo "Gefundene Kernel: $total"
if (( total <= keep )); then
echo "Es gibt nicht mehr Kernel als die zu behaltenden ($keep). Kein Kernel wird entfernt."
return
fi
# Kernel die entfernt werden sollen
to_remove=("${kernels[@]:0:total-keep}")
num_to_remove=${#to_remove[@]}
echo "Folgende Kernel werden entfernt:"
for k in "${to_remove[@]}"; do
echo " - $k"
done
# Nutzer fragt, ob er entfernen will
printf "${bold}[!]${reset} Möchten Sie die ${bold}$num_to_remove${reset} ausgewählten PVE Kernel entfernen? [y/N]: "
read -n 1 -r
printf "\n"
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Abbruch durch Benutzer."
return
fi
# ZFS Snapshot vor dem Löschen
create_snapshot
# Kernel entfernen
for k in "${to_remove[@]}"; do
printf "${bold}[-]${reset} Entferne Kernel-Paket: $k ... "
if [ "$dry_run" = "false" ]; then
apt-get purge -y "$k" > /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 "$@"