pve-kernel-cleaner.sh aktualisiert
This commit is contained in:
+214
-71
@@ -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 "$@"
|
||||||
|
|||||||
Reference in New Issue
Block a user