pve-kernel-cleaner.sh aktualisiert

This commit is contained in:
2025-06-21 01:29:03 +02:00
parent ca48da86b3
commit 3048a2ab6a
+195 -52
View File
@@ -6,20 +6,77 @@
# 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
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 ""
echo "Systeminformationen:"
echo "─────────────────────────────"
current_kernel=$(uname -r)
kernels_installed=($(dpkg --list | awk '/proxmox-kernel-.*-pve-signed/ {print $2}' | sort -V))
num_kernels=${#kernels_installed[@]}
# 1. Prüfen ob EFI oder BIOS
if [ -d /sys/firmware/efi ]; then if [ -d /sys/firmware/efi ]; then
echo "Bootmodus: EFI" echo "Boot-Modus: EFI"
else else
echo "Bootmodus: BIOS (Legacy)" echo "Boot-Modus: Legacy (BIOS)"
fi fi
# 1.1 Subscription-Status prüfen 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 "" echo ""
}
# Prüfe Subscription-Status der APT-Repositories
check_apt_repos() {
echo "APT-Repositories:" echo "APT-Repositories:"
repo_files=$(find /etc/apt/ -name "*.list") repo_files=$(find /etc/apt/ -name "*.list")
@@ -30,64 +87,150 @@ elif grep -rq "no-subscription" $repo_files; then
else else
echo "Kein bekanntes PVE Repository aktiv, prüfe apt-Sources manuell" echo "Kein bekanntes PVE Repository aktiv, prüfe apt-Sources manuell"
fi fi
echo "" echo ""
}
# 2. ZFS Pools prüfen # Snapshot erstellen, falls ZFS vorhanden
echo "ZFS Pool Übersicht:" create_snapshot() {
if command -v zpool &> /dev/null; then if zfs list $ZFS_DATASET &>/dev/null; then
zpool list -Ho name,capacity | while read -r pool cap; do snapshot_name="${ZFS_DATASET}@${SNAPSHOT_TAG}-${TIMESTAMP}"
cap_num=$(echo $cap | tr -d '%') echo "Erstelle ZFS Snapshot: $snapshot_name"
warn="" if [ "$dry_run" = "false" ]; then
if (( cap_num >= 80 )); then zfs snapshot "$snapshot_name" || echo "${red}Snapshot konnte nicht erstellt werden!${reset}"
warn="ACHTUNG: >80% belegt" 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 fi
echo "$pool: $cap $warn"
done done
else fi
echo "ZFS ist nicht installiert oder zpool-Befehl nicht verfügbar." 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 fi
echo "" # Kernel die entfernt werden sollen
to_remove=("${kernels[@]:0:total-keep}")
num_to_remove=${#to_remove[@]}
# 3. Liste der installierten PVE-Kernel anzeigen und alte Kernel identifizieren echo "Folgende Kernel werden entfernt:"
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
echo " - $kernel (alt)"
to_remove+=("$kernel")
fi
done <<< "$kernel_list"
echo ""
if [ ${#to_remove[@]} -eq 0 ]; then
echo "Keine alten Kernel gefunden, nichts zu tun."
exit 0
fi
# 4. Nutzerabfrage zur Entfernung
echo "Die folgenden alten Kernel könnten entfernt werden:"
for k in "${to_remove[@]}"; do for k in "${to_remove[@]}"; do
echo " - $k" echo " - $k"
done done
echo "" # Nutzer fragt, ob er entfernen will
read -p "Möchtest du diese alten Kernel jetzt entfernen? (j/n): " confirm printf "${bold}[!]${reset} Möchten Sie die ${bold}$num_to_remove${reset} ausgewählten PVE Kernel entfernen? [y/N]: "
if [[ "$confirm" =~ ^[Jj]$ ]]; then read -n 1 -r
echo "Entferne alte Kernel..." printf "\n"
apt remove --purge -y "${to_remove[@]}" if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Alte Kernel wurden entfernt." 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 else
echo "Abbruch, keine Kernel wurden entfernt." 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 fi
echo "" echo ""
echo "==== Fertig ====" echo "Fertig."
}
main "$@"