Comment purger de manière sélective les vieux noyaux à la fois

7

Le très apprécié Q & A Comment supprimer les anciennes versions du noyau pour nettoyer le menu de démarrage? ne constitue pas un moyen facile de purger de manière sélective les anciens noyaux, sauf si des applications supplémentaires sont installées, à savoir Ubuntu-Tweak .

Le Bash one-liner pour supprimer uniquement les anciens noyaux Q & A donne une solution "purge all old" mais je veux conserver le dernier noyau de chaque génération. c'est-à-dire supprimer 4.7.1, 4.7.2 ... mais conserver 4.7.5.

Existe-t-il un moyen de parcourir une liste de tous les noyaux installés et de sélectionner des noyaux spécifiques à purger? Il ne doit pas permettre la purge du noyau en cours d’exécution.

    
posée WinEunuuchs2Unix 11.03.2017 - 20:05
la source

1 réponse

5

L'avantage de cette réponse est qu'elle est native Ubuntu Bash est utilisé sans installer d'applications tierces. Les utilisateurs de noyaux personnalisés qui n’utilisaient pas apt ou dpkg peuvent modifier ce script bash en fonction de leurs besoins.

Solution basée sur Zenity

Zenity fournit une interface graphique au terminal. Ici, il est utilisé pour traiter une liste de noyaux et sélectionner des noyaux individuels:

Le titre de la boîte de dialogue indique le nombre de noyaux, leur taille totale et la version actuelle du noyau démarrée. Le noyau actuel est exclu des totaux du titre et n'apparaît pas dans la liste du noyau.

La Date de modification correspond normalement à la date de publication du noyau. Sur mon système, cette date est "touché" chaque fois que le noyau est démarré en utilisant un script de redémarrage cron ( Comment savoir quand une version spécifique du noyau a été démarrée en dernier? ). / p>

Pour chaque noyau, sa taille dans le répertoire /boot est rapportée. La taille totale du noyau est ensuite additionnée pour les trois répertoires. / boot, / usr / src / version_kernel et / lib / modules / version_noyau .

Si aucun paramètre n'est transmis à rm-kernels , la taille totale est estimée et le titre affiche "Est. Total". Cela permet de gagner du temps en exécutant la commande du , ce qui peut prendre entre 30 secondes et 90 minutes, selon le nombre de noyaux que vous avez et si vous avez un disque SSD ou un disque dur. Si vous transmettez un paramètre, du est utilisé pour obtenir les tailles du noyau et le titre affiche "Real Total" comme illustré ci-dessus.

apt-get purge vous donne une chance d'abandonner

Vous pouvez voir tout ce qui sera purgé par apt purge et vous avez la possibilité de continuer ou d’annuler:

The following packages will be REMOVED:
  linux-headers-4.4.0-78* linux-headers-4.4.0-78-generic*
  linux-headers-4.4.8-040408* linux-headers-4.4.8-040408-generic*
  linux-headers-4.6.3-040603* linux-headers-4.6.3-040603-generic*
  linux-headers-4.8.12-040812* linux-headers-4.8.12-040812-generic*
  linux-headers-4.9.0-040900* linux-headers-4.9.0-040900-generic*
  linux-headers-4.9.9-040909* linux-headers-4.9.9-040909-generic*
  linux-image-4.4.0-78-generic* linux-image-4.4.8-040408-generic*
  linux-image-4.6.3-040603-generic* linux-image-4.8.12-040812-generic*
  linux-image-4.9.0-040900-generic* linux-image-4.9.9-040909-generic*
  linux-image-extra-4.4.0-78-generic*
0 upgraded, 0 newly installed, 19 to remove and 1 not upgraded.
After this operation, 1,794 MB disk space will be freed.
Do you want to continue? [Y/n] 

apt purge rapporte que 1 784 Mo seront libérés, mais que le total réel est de 2 379 Mo. Je ne sais pas pourquoi c'est différent.

Plutôt que de purger les noyaux un à la fois et que update-grub soit appelé de manière répétitive dans une boucle qui prend du temps, les sélections sont purgées en une seule fois.

Le code

Copiez ce code dans un fichier nommé rm-kernels in /usr/local/bin :

#!/bin/bash

# NAME: rm-kernels
# PATH: /usr/local/bin
# DESC: Provide zenity item list of kernels to remove

# DATE: Mar 10, 2017. Modified Aug 5, 2017.

# NOTE: Will not delete current kernel.

#       With 10 kernels on an SSD, empty cache from sudo prompt (#) using:
#       # free && sync && echo 3 > /proc/sys/vm/drop_caches && free
#       First time for 'du' 34 seconds.
#       Second time for 'du' 1 second.
#       With a magnetic hard disk, and empty memory cache:
#       the first 'du' command averages about 20 seconds per kernel.
#       the second 'du' command averages about 2.5 seconds per kernel.

# PARM: If any parm 1 passed use REAL kernel size, else use estimated size.
#       By default 'du' is not used and estimated size is displayed.

# Must be running as sudo
if [[ $(id -u) != 0 ]]; then
    zenity --error --text "root access required. Use: sudo rm-kernels"
    exit 99
fi

OLDIFS="$IFS"
IFS="|"
choices=()

current_version=$(uname -r)

for f in /boot/vmlinuz*
do
    if [[ $f == *"$current_version"* ]]; then continue; fi # skip current version
    [[ $f =~ vmlinuz-(.*) ]]
    v=${BASH_REMATCH[1]}        # example: 4.9.21-040921-generic
    v_main="${v%-*}"            # example: 4.9.21-040921

    n=$(( n + 1 ))              # increment number of kernels

    # Kernel size in /boot/*4.9.21-040921-generic*
    s=$(du -ch /boot/*-$v* | awk '/total/{print }')

    if [[ $# -ne 0 ]] ; then    # Was a parameter passed?
        if [[ -d "/usr/src/linux-headers-"$v_main ]] ; then
             # Kernel headers size in /usr/src/*4.9.21-040921*
             s2=$(du -ch --max-depth=1 /usr/src/*-$v_main* | awk '/total/{print }')
        else
             s2="0M"            # Linux Headers are not installed
        fi
        # Kernel image size in /lib/modules/4.9.21-040921-generic*
        s3=$(du -ch --max-depth=1 /lib/modules/$v* | awk '/total/{print }')
    else
        # Estimate sizof of optional headers at 125MB and size of image at 220MB
        if [[ -d "/usr/src/linux-headers-"$v_main ]] ; then
             s2="125M"
        else
             s2="0M"            # Linux Headers are not installed
        fi
        s3="220M"
    fi

    # Strip out "M" provided by human readable option of du and add 3 sizes together
    c=$(( ${s//[^0-9]*} + ${s2//[^0-9]*} + ${s3//[^0-9]*} ))
    s=$(( ${s//[^0-9]*} )) # Strip out M to make " MB" below which looks nicer
    t=$(( t + c ))
    s=$s" MB"
    c=$c" MB"
    d=$(date --date $(stat -c %y $f) '+%b %d %Y') # Last modified date for display
    choices=("${choices[@]}" false "$v" "$d" "$s" "$c")
done

# Write Kernel version and array index to unsorted file
> ~/.rm-kernels-plain # Empty any existing file.
for (( i=1; i<${#choices[@]}; i=i+5 )) ; do
    echo "${choices[i]}|$i" >> ~/.rm-kernels-plain
done

# Sort kernels by version number
sort -V -k1 -t'|' ~/.rm-kernels-plain -o ~/.rm-kernels-sorted

# Strip out keys leaving Sorted Index Numbers
cut -f2 -d '|' ~/.rm-kernels-sorted > ~/.rm-kernels-ndx

# Create sorted array
SortedArr=()
while read -r ndx; do 
    end=$(( ndx + 4 ))
    for (( i=$(( ndx - 1 )); i<end; i++ )); do
        SortedArr+=("${choices[i]}")
    done
done < ~/.rm-kernels-ndx

rm ~/.rm-kernels-plain ~/.rm-kernels-sorted ~/.rm-kernels-ndx

if [[ $# -ne 0 ]] ; then    # Was a parameter passed?
    VariableHeading="Real Total"
else
    VariableHeading="Est. Total"
fi

# adjust width & height below for your screen 640x480 default for 1920x1080 HD screen
# also adjust font="14" below if blue text is too small or too large

choices=('zenity \
        --title "rm-kernels - $n Kernels, Total: $t MB excluding: $current_version" \
        --list \
        --separator="$IFS" \
        --checklist --multiple \
        --text '<span foreground="blue" font="14">Check box next to kernel(s) to remove</span>' \
        --width=800 \
        --height=480 \
        --column "Select" \
        --column "Kernel Version Number" \
        --column "Modified Date" \
        --column "/boot Size" \
        --column "$VariableHeading" \
        "${SortedArr[@]}"')
IFS="$OLDIFS"

i=0
list=""
for choice in "${choices[@]}" ; do
    if [ "$i" -gt 0 ]; then list="$list- "; fi # append "-" from last loop
    ((i++))

    short_choice=$(echo $choice | cut -f1-2 -d"-")
    header_count=$(find /usr/src/linux-headers-$short_choice* -maxdepth 0 -type d | wc -l)

    # If -lowlatency and -generic are purged at same time the _all header directory
    # remains on disk for specific version with no -generic or -lowlatency below.
    if [[ $header_count -lt 3 ]]; then
        # Remove all w.x.y-zzz headers
        list="$list""linux-image-$choice- linux-headers-$short_choice"
    else
        # Remove w.x.y-zzz-flavour header only, ie -generic or -lowlatency
        list="$list""linux-image-$choice- linux-headers-$choice" 
    fi

done

if [ "$i" -gt 0 ] ; then
     apt-get purge $list
fi

REMARQUE: vous devez utiliser sudo powers pour enregistrer le fichier avec votre éditeur favori.

Pour rendre le fichier exécutable, utilisez

sudo chmod +x /usr/local/bin/rm-kernels

Version du serveur

rm-kernels-server est la version du serveur pour supprimer de manière sélective les noyaux en une seule fois. Au lieu d'une boîte de dialogue graphique (GUI), une boîte de dialogue textuelle est utilisée pour sélectionner les noyaux à purger.

  • Avant d’exécuter le script, vous devez installer la fonction de dialogue en utilisant:

    sudo apt install dialog

Dialog se trouve dans l’installation par défaut d’Ubuntu Desktop, mais pas dans Ubuntu Server.

Exemple d'écran

rm-kernels-server bash code

#!/bin/bash

# NAME: rm-kernels-server
# PATH: /usr/local/bin
# DESC: Provide dialog checklist of kernels to remove
#       Non-GUI, text based interface for server distro's.

# DATE: Mar 10, 2017. Modified Aug 5, 2017.

# NOTE: Will not delete current kernel.

#       With 10 kernels on an SSD, empty cache from sudo prompt (#) using:
#       # free && sync && echo 3 > /proc/sys/vm/drop_caches && free
#       First time for 'du' 34 seconds.
#       Second time for 'du' 1 second.
#       With a magnetic hard disk, and empty memory cache:
#       the first 'du' command averages about 20 seconds per kernel.
#       the second 'du' command averages about 2.5 seconds per kernel.

# PARM: If any parm 1 passed use REAL kernel size, else use estimated size.
#       By default 'du' is not used and estimated size is displayed.

# Must be running as sudo
if [[ $(id -u) != 0 ]]; then
    echo "root access required. Use: sudo rm-kernels-server"
    exit 99
fi

# Must have the dialog package. On Servers, not installed by default
command -v dialog >/dev/null 2>&1 || { echo >&2 "dialog package required but it is not installed.  Aborting."; exit 99; }

OLDIFS="$IFS"
IFS="|"
item_list=() # Deviate from rm-kernels here.

current_version=$(uname -r)
i=0
for f in /boot/vmlinuz*
do
    if [[ $f == *"$current_version"* ]]; then continue; fi # skip current version
    [[ $f =~ vmlinuz-(.*) ]]
    ((i++)) # Item List
    v=${BASH_REMATCH[1]}        # example: 4.9.21-040921-generic
    v_main="${v%-*}"            # example: 4.9.21-040921

    n=$(( n + 1 ))              # increment number of kernels

    # Kernel size in /boot/*4.9.21-040921-generic*
    s=$(du -ch /boot/*-$v* | awk '/total/{print }')

    if [[ $# -ne 0 ]] ; then    # Was a parameter passed?
        if [[ -d "/usr/src/linux-headers-"$v_main ]] ; then
             # Kernel headers size in /usr/src/*4.9.21-040921*
             s2=$(du -ch --max-depth=1 /usr/src/*-$v_main* | awk '/total/{print }')
        else
             s2="0M"            # Linux Headers are not installed
        fi
        # Kernel image size in /lib/modules/4.9.21-040921-generic*
        s3=$(du -ch --max-depth=1 /lib/modules/$v* | awk '/total/{print }')
    else
        # Estimate sizof of optional headers at 125MB and size of image at 220MB
        if [[ -d "/usr/src/linux-headers-"$v_main ]] ; then
             s2="125M"
        else
             s2="0M"            # Linux Headers are not installed
        fi
        s3="220M"
    fi

    # Strip out "M" provided by human readable option of du and add 3 sizes together
    c=$(( ${s//[^0-9]*} + ${s2//[^0-9]*} + ${s3//[^0-9]*} ))
    s=$(( ${s//[^0-9]*} )) # Strip out M to make " MB" below which looks nicer
    t=$(( t + c ))
    s=$s" MB"
    c=$c" MB"
    d=$(date --date $(stat -c %y $f) '+%b %d %Y') # Last modified date for display
    item_list=("${item_list[@]}" "$i" "$v ! $d ! $s ! $c" off)
done

# Write Kernel version and array index to unsorted file
> ~/.rm-kernels-plain # Empty any existing file.
for (( i=1; i<${#item_list[@]}; i=i+3 )) ; do
    echo "${item_list[i]}|$i" >> ~/.rm-kernels-plain
done

# Sort kernels by version number
sort -V -k1 -t'|' ~/.rm-kernels-plain -o ~/.rm-kernels-sorted

# Strip out keys leaving Sorted Index Numbers
cut -f2 -d '|' ~/.rm-kernels-sorted > ~/.rm-kernels-ndx

# Create sorted array
SortedArr=()
i=1
while read -r ndx; do 
    SortedArr+=($i "${item_list[$ndx]}" "off")
    (( i++ ))
done < ~/.rm-kernels-ndx

rm ~/.rm-kernels-plain ~/.rm-kernels-sorted ~/.rm-kernels-ndx

cmd=(dialog --backtitle "rm-kernels-server - $n Kernels, Total: $t MB excluding: $current_version" \
    --title "Use space bar to toggle kernel(s) to remove" \
    --column-separator "!" \
    --separate-output \
    --ascii-lines \
    --checklist "         Kernel Version  ------  Modified Date /boot Size  Total" 20 70 15)

selections=$("${cmd[@]}" "${SortedArr[@]}" 2>&1 >/dev/tty)

IFS=$OLDIFS

if [ $? -ne 0 ] ; then
    echo cancel selected
    exit 1
fi

i=0
choices=()

for select in $selections ; do
    ((i++))
    j=$(( 1 + ($select - 1) * 3 ))
    choices[i]=$(echo ${SortedArr[j]} | cut -f1 -d"!")
done

i=0
list=""
for choice in "${choices[@]}" ; do
    if [ "$i" -gt 0 ]; then list="$list- "; fi # append "-" from last loop
    ((i++))

    short_choice=$(echo $choice | cut -f1-2 -d"-")
    header_count=$(find /usr/src/linux-headers-$short_choice* -maxdepth 0 -type d | wc -l)

    # If -lowlatency and -generic are purged at same time the _all header directory
    # remains on disk for specific version with no -generic or -lowlatency below.
    if [[ $header_count -lt 3 ]]; then
        # Remove all w.x.y-zzz headers
        list="$list""linux-image-$choice- linux-headers-$short_choice"
    else
        # Remove w.x.y-zzz-flavour header only, ie -generic or -lowlatency
        list="$list""linux-image-$choice- linux-headers-$choice" 
    fi

done

if [ "$i" -gt 0 ] ; then
    apt-get purge $list
fi

REMARQUE: Dans l’appel à dialog , la directive --ascii-lines est passée pour remplacer le jeu de caractères étendu dessiné par une ligne (ce que ssh n’aime pas) avec "+ --- - + "pour les boîtes à dessin. Si vous n'aimez pas cette apparence, vous pouvez utiliser la directive --no-lines pour aucune case. Si vous n'utilisez pas ssh , vous pouvez supprimer --ascii-lines et votre affichage sera mis en forme avec des caractères linéaires:

Mise à jour du 28 juillet 2017

La taille calculée de chaque noyau provient de /boot/*kernel_version* , soit 5 fichiers totalisant environ 50 Mo. La formule a été modifiée pour inclure les fichiers dans /usr/src/*kernel_version* et /lib/modules/*kernel_version* . La taille calculée pour chaque noyau est maintenant d'environ 400 Mo.

La valeur par défaut est d’estimer la taille des fichiers pour les en-têtes linux à 125 Mo et linux-image à 220 Mo car du peut être très lent à moins que les fichiers ne soient en mémoire cache. Pour obtenir la taille réelle à l'aide de du , passez un paramètre au script.

Le total de toutes les tailles de noyau (à l’exclusion de la version en cours d’exécution qui ne peut pas être supprimée) est maintenant affiché dans la barre de titre.

La boîte de dialogue utilisée pour afficher chaque noyau Date du dernier accès . Cette date peut être écrasée en masse pour tous les noyaux lors d'une sauvegarde ou d'une opération similaire. La boîte de dialogue affiche maintenant la Date de modification à la place.

Mises à jour du 5 août 2017

La liste du noyau est maintenant triée par version du noyau plutôt que par ordre alphabétique.

Une colonne supplémentaire a été ajoutée pour /boot size . Dans la version graphique de Zenity, la dernière colonne change entre "Total réel" et "Total est." (Estimation) en fonction du paramètre 1 transmis ou non.

    
réponse donnée WinEunuuchs2Unix 11.03.2017 - 20:05
la source

Lire d'autres questions sur les étiquettes