Ubuntu : mise à jour du noyau et aucun espace disponible sur le périphérique

Table des matières

Avec la distribution Ubuntu, on a très souvent de nombreuses mises à jour du noyau. On peut se demander pourquoi il y a si souvent des mises à jour, on peut aussi féliciter Ubuntu pour veiller aussi scrupuleusement à corriger les failles ou les bugs des noyaux. L’approche d’Ubuntu et de Canonical à ce niveau est discutable, on pourrait en débattre pendant des heures, mais les faits sont là : toutes ces mises à jour saturent parfois les systèmes et posent des problèmes à des néophytes qui n’ont rien demandé.

Dommage, pour une fois ce n’est pas un PEBKAC, c’est bel et bien un problème inhérent à la distribution. Des mesures correctrices sont en train d’être mises en place, espérons que tout ceci se fera automatiquement pour la prochaine version « LTS », toujours est-il qu’il faut bien traiter ce problème aujourd’hui…

Le problème ? On fait une mise à jour, celle-ci inclut un noyau et ses en-têtes (paquets linux-image-* et linux-headers-*) et paf ! grosse erreur, les mises à jour sont bloquées, on ne peut plus rien installer…

Avertissement : cet article est long : il explique clairement le problème, ses sources, les implications et les façons de le résoudre et de l’éviter. Ça ne peut pas se faire en une dizaine de lignes.

Pré-requis

Avant de se lancer dans la procédure que je vais décrire, il faut savoir ce qu’est un terminal.

Le « terminal » est l’interface textuelle permettant à un utilisateur de transmettre des instructions au système. Quand on lance un terminal, on se retrouve devant un prompt comme celui-ci :

sebastien@amaretto:~$

Ici :

  • « sebastien » est le nom de l’utilisateur (moi, en l’occurrence) ;
  • « amaretto » est le nom de l’ordinateur ;
  • « ~ » est le nom du répertoire où on est situé ( »~ » est l’abréviation pour le répertoire utilisateur) ;
  •  »$ » signifie qu’on est connecté en utilisateur simple et pas en tant que « root ».

On peut alors taper des commandes pour obtenir des résultats.

Pour fermer le terminal, il suffit de cliquer sur le bouton idoine de la fenêtre (généralement une croix en haut à droite ou à gauche) ou alors de taper :

exit

Comment savoir si on a ce problème

Lorsque l’on rencontre un problème bloquant les mise à jour, comment être sûr que c’est bien à celui dont je parle qu’on est confronté ? Il suffit de regarder le messages d’erreur !

Dans un terminal, exécuter la commande suivante :

sudo apt-get upgrade

Cette commande a pour objectif de mettre à jour le système (c’est ce qui est exécuté par l’interface graphique quand on demande de mettre à jour). Elle demandera certainement votre mot de passe ; rien ne s’affiche lorsqu’on le tape, c’est normal, il ne faut pas s’en inquiéter.

Si on a un problème de mise à jour avec l’interface graphique, c’est que cette commande échoue. Par conséquent, en la tapant dans le terminal, elle échoue également. Il faut alors chercher, dans l’imposant message retourné par cette commande, la raison première du blocage. Dans le cas qui nous intéresse ici, on doit avoir un message qui ressemble à ça :

impossible de créer « /usr/src/linux-headers-X.X.X-XXXXXXX » (pendant le traitement de « ./usr/src/linux-headers-X.X.X-XXXXXXX »): Aucun espace disponible sur le périphérique

La partie importante est « Aucun espace disponible sur le périphérique ». Voilà, il s’agit d’un problème d’espace disque insuffisant, lors de l’installation d’un paquet « linux-headers » ou d’un paquet « linux-image ».

Pour la suite, si vous ne voulez pas comprendre le contexte, vous pouvez sauter le chapitre « Les causes du problèmes » pour passer directement au chapitre « Résolution ».

Si vous ne rencontrez pas le problème mais que vous voulez vous en prémunir, vous pouvez sauter directement au chapitre « Nettoyer le système ».

Les causes du problème

Le noyau Linux et sa taille

Le noyau, c’est le moteur du système. C’est Linux tout court. Tout ce qu’il y a autour, ce sont d’autres logiciels, qui composent la distribution. Linux, c’est le « moteur » d’Ubuntu.

Et ce « moteur », il a besoin de mises à jour, soit pour corriger des bugs, soit pour corriger des failles de sécurité, soit pour offrir de nouvelles fonctionnalités. Ubuntu propose donc régulièrement ces mises à jour, que tout utilisateur consciencieux fera en toute confiance.

De plus, tout noyau est accompagné de ses en-têtes : ce sont des fichiers qui permettent de compiler des modules qui ne sont pas fournis par défaut dans le système noyau : par exemple (et bien souvent) les pilotes NVidia privateurs, permettant d’utiliser au mieux les fonctionnalités 3D des cartes graphiques NVidia.

Sauf qu’un noyau, c’est gros. En taille de fichier mais aussi en nombre de fichiers :

  • pour le noyau lui-même, il faut compter entre 150 et 200 Mo, pour 3500 ou 4000 fichiers ;
  • pour les en-têtes du noyau, il faut compter environ 100 Mo, pour 15000 à 20000 fichiers (non non, je n’ai pas fait de faute, il n’y a pas un zéro en trop).

De nombreux noyaux

À chaque mise à jour du noyau, le précédent n’est pas remplacé par le nouveau : ce dernier s’installe en complément.

Pourquoi ? Tout simplement parce que si l’installation du nouveau noyau rencontre le moindre problème, le système ne pourra jamais démarrer dessus. Il est donc préférable de garder au moins un précédent noyau, pour démarrer dessus si jamais le nouveau noyau ne fonctionne pas.

Cela veut dire que les noyaux s’accumulent au fur et à mesure, parfois par dizaines. Une procédure facilitant la suppression des anciens noyaux est en train d’être mise en place, mais elle n’est pas encore généralisée.

Et les systèmes de fichiers sont limités en nombre de fichiers que l’on peut stocker : tout fichier est référencé dans la table des inodes du système de fichiers, qui peut être considérée comme un « sommaire » permettant de savoir où est placé chacun des fichiers.

Lorsqu’il y a un seul système de fichiers, alors on a énormément de marge : sur un disque qui fait plusieurs centaines de giga-octets, on a de quoi voir venir, et on ne rencontre pour ainsi dire jamais ce problème.

Par contre, dans le cas le plus courant, lorsque l’on a proprement un système de fichiers « racine » et un système de fichiers « /home », le premier a souvent un espace limité : 10, 20 ou 30 Go par exemple. Et en temps normal, c’est largement suffisant.

Un système de fichiers d’environ 30 Go (comme le mien) a environ 1900000 inodes disponibles. Je n’ai pour ma part jamais rencontré ce problème sur un système de fichiers de 30 Go. Prenons comme exemple un système de fichiers de 15 Go, qui a alors moins d’un million d’inodes.

Si on a 30 mises à jour différentes du noyau (et de ses en-têtes) installées (on peut y arriver assez facilement, en ne nettoyant pas les noyaux pendant plusieurs mois), on a donc environ…

(200 + 100) × 30 = 9 Go

(20000 + 4000) × 30 = 720000 inodes

9 Go, c’est une place conséquente, mais ça pourrait encore passer : ça représente 60% de 15 Go et Ubuntu n’est pas spécialement gourmand. 720000 inodes, par contre, ça représente environ 75% du système de fichiers, utilisés rien que pour les noyaux. Il y a encore le reste du système à stocker !

Forcément, au bout d’un moment, ça coince…

Heureusement, c’est (à ma connaissance) le seul point qui pose problème dans cette politique de mise à jour d’Ubuntu : aucun autre paquet ne fonctionne de cette manière.

Résolution

Voir le problème, concrètement

Tout d’abord, regardons l’espace libre sur le disque, en terme d’octets et en terme d’inodes… Cela se fait avec les commandes df -h et df -i. Ci-dessous l’exemple de mon ordinateur, qui a largement assez de place :

sebastien@amaretto:~$ df -h
Sys. de fichiers Taille Utilisé Dispo Uti% Monté sur
/dev/sda2           29G    7,9G   19G  30% /
none               4,0K       0  4,0K   0% /sys/fs/cgroup
udev               7,8G    4,0K  7,8G   1% /dev
tmpfs              1,6G    1,1M  1,6G   1% /run
none               5,0M       0  5,0M   0% /run/lock
none               7,8G    4,4M  7,8G   1% /run/shm
none               100M     76K  100M   1% /run/user
/dev/sda4          429G    313G  116G  74% /home
/dev/sda1           93M    2,2M  91M    3% /boot/efi
sebastien@amaretto:~$ df -i
Sys. de fichiers Inœuds IUtil.   ILibre IUti% Monté sur
/dev/sda2       1875968 358314  1517654   20% /
none            2031106      1  2031105    1% /sys/fs/cgroup
udev            2028720    599  2028121    1% /dev
tmpfs           2031106    607  2030499    1% /run
none            2031106      4  2031102    1% /run/lock
none            2031106     21  2031085    1% /run/shm
none            2031106     81  2031025    1% /run/user
/dev/sda4      28524544 176574 28347970    1% /home
/dev/sda1             0      0        0     - /boot/efi

J’ai mis en gras les lignes qui nous intéressent : celles qui correspondent au périphérique monté sur /. J’ai 19 Go de libres, pour 1517654 inodes. C’est bon, j’ai de la place. Si vous avez le problème dont on parle, chez vous vous avez certainement une valeur proche de zéro, soit dans la colonne « Dispo » du df -h soit dans la colonne « ILibre » du df -i. Vous êtes plus probablement dans le second cas.

Et qui c’est qui prend toute la place ?

Pour la réponse à cette question, je vais faire un peu de divination… je dirais… les noyaux et leurs en-têtes !!!

Comment le vérifier ? Avec les commandes dpkg -l | grep ^ii.\*linux-image et dpkg -l \| grep ^ii.\*linux-headers (tout simplement, dirait un linuxien aguerri).

Voici par exemple le retour de ces commandes chez moi :

sebastien@amaretto:~$ dpkg -l | grep ^ii.*linux-image
ii linux-image-3.8.0-19-generic 3.8.0-19.30 amd64 Linux kernel image for version 3.8.0 on 64 bit x86 SMP
ii linux-image-3.8.0-29-generic 3.8.0-29.42 amd64 Linux kernel image for version 3.8.0 on 64 bit x86 SMP
ii linux-image-3.8.0-31-generic 3.8.0-31.46 amd64 Linux kernel image for version 3.8.0 on 64 bit x86 SMP
ii linux-image-3.8.0-32-generic 3.8.0-32.47 amd64 Linux kernel image for version 3.8.0 on 64 bit x86 SMP
ii linux-image-extra-3.8.0-19-generic 3.8.0-19.30 amd64 Linux kernel image for version 3.8.0 on 64 bit x86 SMP
ii linux-image-extra-3.8.0-29-generic 3.8.0-29.42 amd64 Linux kernel image for version 3.8.0 on 64 bit x86 SMP
ii linux-image-extra-3.8.0-31-generic 3.8.0-31.46 amd64 Linux kernel image for version 3.8.0 on 64 bit x86 SMP
ii linux-image-extra-3.8.0-32-generic 3.8.0-32.47 amd64 Linux kernel image for version 3.8.0 on 64 bit x86 SMP
ii linux-image-generic 3.8.0.32.50 amd64 Generic Linux kernel image
sebastien@amaretto:~$ dpkg -l | grep ^ii.*linux-headers
ii linux-headers-3.8.0-19 3.8.0-19.30 all Header files related to Linux kernel version 3.8.0
ii linux-headers-3.8.0-19-generic 3.8.0-19.30 amd64 Linux kernel headers for version 3.8.0 on 64 bit x86 SMP
ii linux-headers-3.8.0-29 3.8.0-29.42 all Header files related to Linux kernel version 3.8.0
ii linux-headers-3.8.0-29-generic 3.8.0-29.42 amd64 Linux kernel headers for version 3.8.0 on 64 bit x86 SMP
ii linux-headers-3.8.0-31 3.8.0-31.46 all Header files related to Linux kernel version 3.8.0
ii linux-headers-3.8.0-31-generic 3.8.0-31.46 amd64 Linux kernel headers for version 3.8.0 on 64 bit x86 SMP
ii linux-headers-3.8.0-32 3.8.0-32.47 all Header files related to Linux kernel version 3.8.0
ii linux-headers-3.8.0-32-generic 3.8.0-32.47 amd64 Linux kernel headers for version 3.8.0 on 64 bit x86 SMP
ii linux-headers-generic 3.8.0.32.50 amd64 Generic Linux kernel headers

J’ai un nombre raisonnable de noyaux. Si vous avez le problème dont je parle, chacune de ces commandes vous retourne de très nombreuses lignes.

Ce qu’il faudrait faire

C’est simple : il faut libérer de l’espace disque. Et si vous avez un peu de logique, votre réaction devrait être : « eh bien ! désinstallons simplement les anciens noyaux ! ».

Oui mais non… dpkg, l’outil de gestion des paquets d’Ubuntu, ne sait faire qu’une chose à la fois. Et, pour faire une nouvelle action, il faut que l’action précédente soit terminée. C’est bien, car ça permet de ne pas faire de bêtises : la meilleure façon de ne rien casser, c’est de faire une chose à la fois.

Dans le cas qui nous intéresse, l’action précédente n’est pas terminée : c’est l’installation du nouveau noyau (ou de ses nouveaux en-têtes), qui a échoué par manque de place. C’est le serpent qui se mord la queue !

Un peu de bricolage à la main

Habituellement, il ne faut surtout pas effacer à la main des fichiers gérés par dpkg. Mais là, on n’a pas le choix : il faut le décoincer !

On va alors identifier ce que l’on peut supprimer sans incidence malheureuse. Si on reprend les chiffres qu’on a vus plus haut, on voit qu’un ensemble noyau+en-têtes représente environ 24000 inodes. Pour avoir de la marge, prévoyons d’en libérer plus.

Le plus simple, en restant logique, est alors de supprimer deux paquets d’en-têtes : on libérera alors jusqu’à 40000 inodes. Les en-têtes sont nécessaires à la compilation de nouveaux modules, mais pas au fonctionnement du système au jour le jour. Donc au pire, si on supprime les mauvais en-têtes, on ne cassera pas le système. Bon, bien sûr, restons vigilants et ne supprimons pas ceux qu’on veut garder…

Reprenons alors le retour de la commande dpkg -l | grep linux-headers vue plus haut. Elle donne la liste de tous les headers installés. Chez moi, les deux plus anciens sont linux-headers-3.8.0-19 et linux-headers-3.8.0-29, avec leurs pendants -generic. Chez vous, les versions de ces paquets seront bien sûr différents : chacun identifiera quelles sont les deux plus anciennes versions chez lui.

On supprime alors les fichiers correspondant à ces en-têtes. C’est assez simple : les fichiers des en-têtes sont placées dans le répertoire /usr/src, dans un sous-répertoire nommé comme le paquet.

Ces paquets doivent être supprimés avec les « droits root », on utilisera donc la commande sudo.

Chez moi, les commandes seront donc :

sebastien@amaretto:~$ sudo rm -fr /usr/src/linux-headers-3.8.0-19
[sudo] password for sebastien:
sebastien@amaretto:~$ sudo rm -fr /usr/src/linux-headers-3.8.0-19-generic
sebastien@amaretto:~$ sudo rm -fr /usr/src/linux-headers-3.8.0-29
sebastien@amaretto:~$ sudo rm -fr /usr/src/linux-headers-3.8.0-29-generic

À vous d’adapter la commande, en remplaçant le numéro de version par celui correspondant à vos deux plus anciens paquets d’en-têtes.

Lors de la première utilisation de sudo, mon mot de passe est demandé afin de valider que c’est bien moi qui tape ces commandes et que je suis sûr de ce que je veux faire. Lorsque l’on tape le mot de passe, rien n’apparaît : c’est normal, le logiciel reçoit bien les caractères que l’on tape. Lors des autres utilisations, c’est bon on est identifié, le mot de passe n’est plus demandé.

commande df -i :
commande df -i :
commande df -i :
commande df -i :
de df -i :

::

sebastien@amaretto:~$ df -i
Sys. de fichiers Inœuds IUtil.   ILibre IUti% Monté sur
/dev/sda2       1875968 310993  1564975   17% /
none            2031106      1  2031105    1% /sys/fs/cgroup
udev            2028720    599  2028121    1% /dev
tmpfs           2031106    607  2030499    1% /run
none            2031106      4  2031102    1% /run/lock
none            2031106     21  2031085    1% /run/shm
none            2031106     81  2031025    1% /run/user
/dev/sda4      28524544 176574 28347970    1% /home
/dev/sda1             0      0        0     - /boot/efi

On voit que j’ai gagné 47321 inodes. Chez vous, si la valeur ILibre était proche du zéro, vous devriez être aux alentours de 40000 : c’est bon, on peut débloquer dpkg !

Débloquer dpkg

En fait, dpkg est utilisé indirectement, par l’intermédiaire du logiciel apt (lui-même utilisé par l’intermédiaire de la logithèque, si on utilise la logithèque).

La commande à exécuter est simplement celle qui échouait plus haut :

sudo apt-get upgrade

Cette commande devrait alors se terminer sans erreur.

S’il y a toujours une erreur à la mise à jour, alors n’hésitez pas à créer une discussion sur le forum Ubuntu-fr en indiquant les manipulations que vous avez effectuées et l’erreur que vous avez rencontrée. Car si vous avez encore une erreur ici (et si vous avez scrupuleusement suivi mes instructions), cela veut dire que vous avez un autre problème.

Désinstaller proprement ce qu’on a supprimé

On a supprimé des fichiers avec la commande « rm », mais on n’a pas désinstallé les paquets du système. Afin de ne pas embrouiller l’ordinateur, maintenant que dpkg est débloqué, demandons-lui de supprimer les paquets concernés.

Voici les commandes utilisées chez moi, encore une fois à vous d’adapter les numéros de versions à vos plus anciennes versions des en-têtes :

sebastien@amaretto:~$ sudo apt-get remove --purge linux-headers-3.8.0-19
[sudo] password for sebastien:
Lecture des listes de paquets... Fait
Construction de l'arbre des dépendances
Lecture des informations d'état... Fait
Les paquets suivants seront ENLEVÉS :
    linux-headers-3.8.0-19* linux-headers-3.8.0-19-generic*
0 mis à jour, 0 nouvellement installés, 2 à enlever et 34 non mis à jour.
Après cette opération, 72,1 Mo d'espace disque seront libérés.
Souhaitez-vous continuer [O/n] ? o
(Lecture de la base de données... 326460 fichiers et répertoires déjà installés.)
Suppression de linux-headers-3.8.0-19-generic ...
Suppression de linux-headers-3.8.0-19 ...
sebastien@amaretto:~$ sudo apt-get remove --purge linux-headers-3.8.0-29
Lecture des listes de paquets... Fait
Construction de l'arbre des dépendances
Lecture des informations d'état... Fait
Les paquets suivants seront ENLEVÉS :
    linux-headers-3.8.0-29* linux-headers-3.8.0-29-generic*
0 mis à jour, 0 nouvellement installés, 2 à enlever et 34 non mis à jour.
Après cette opération, 72,1 Mo d'espace disque seront libérés.
Souhaitez-vous continuer [O/n] ? o
(Lecture de la base de données... 302800 fichiers et répertoires déjà installés.)
Suppression de linux-headers-3.8.0-29-generic ...
Suppression de linux-headers-3.8.0-29 ...

Lorsque la commande demande « Souhaitez-vous continuer [O/n] ?« , il faut taper sur la touche entrée pour confirmer « oui » (le « O » est en majuscule, cela veut dire que c’est le choix par défaut) ; on peut aussi répondre simplement « o » (majuscule ou minuscule, ça ne change rien).

On est alors retourné dans un état stable, où dpkg n’est pas bloqué et où les fichiers sur le système correspondent aux paquets installés…

Nettoyer le système

Il reste alors à nettoyer le système pour ne pas rencontrer à nouveau ce problème à la prochaine mise à jour du noyau. Il y a pour cela différentes méthodes :

  • on peut désinstaller soi-même avec la commande sudo apt-get remove --purge presque tous les paquets « linux-image-XXX » et « linux-headers-XXX » en gardant les deux les plus récents, cette méthode est expliquée dans la documentation d’Ubuntu-fr ;
  • le logiciel ubuntu-tweak offre de très nombreuses fonctionnalités, dont la possibilité de désinstaller les anciens noyaux : c’est un peu une usine à gaz, mais il peut aussi répondre à d’autres problématiques…
  • le script kclean, développé par Hoper (bénévole d’Ubuntu-fr), permet de faire cela simplement : il ne fait que ça et il le fait bien.

Il restera ensuite simplement à nettoyer régulièrement les anciens noyaux, avec l’une de ces trois méthodes. Régulièrement, oui mais… à quelle fréquence ? C’est simple : depuis combien de temps avez-vous installé votre ordinateur et n’avez-vous pas nettoyé les noyaux ? Si vous avez installé Ubuntu il y a 1 an, cela veut dire qu’il faut 1 an à votre système pour avoir trop de noyaux installés ; un nettoyage tous les 9 mois est alors suffisant.

Chacun choisira la méthode qu’il préfère. Les trois liens que j’indique dans cette liste vous donnent les pistes afin d’effectuer ce nettoyage !

Pour ma part, j’aime bien faire les choses à la main, alors j’identifie les paquets à supprimer avec les commandes dpkg -l | grep linux-image et dpkg -l | grep linux-headers comme on les a vues plus haut, j’exclus les deux derniers numéros de versions et j’utilise sudo apt-get remove --purge pour supprimer tous les autres, comme indiqué dans le chapitre « Désinstaller proprement ce qu’on a supprimé ».

Sur le même sujet

comments powered by Disqus