vendredi 1er mai 2015
Certaines distributions Linux, ou certaines versions de ces distributions, ne disposent pas toujours pour certains matériels de pilotes pré-compilés en paquets rpm/apt (RedHat/Debian) que l’on peut installer simplement.
Il faut alors récupérer le pilote dans une archive, à décompresser et à compiler.
Dans le cas des cartes graphiques Nvidia, il s’agit d’un blob, un script contenant un logiciel.
Dans le monde des logiciels libres, le BLOB est un terme péjoratif pour désigner l’inclusion d’un pilote sous forme de fichier objet dans le noyau libre d’un système d’exploitation afin de ne pas divulguer le code source du programme. On retrouve ces blobs dans les systèmes NetBSD, FreeBSD, DragonFly BSD et la plupart des distributions GNU/Linux.
Source : Wikipedia
Dès lors, il faut, après chaque mise à jour du noyau Linux, le kernel
, recompiler le module noyau correspondant au pilote ou ré-exécuter le script d’installation du pilote, dans le cas par exemple du pilote Nvidia.
Il est ici question du pilote Nvidia, mais le même type de procédure peut être utilisé pour d’autres modules, comme par exemple bbswitch.
Pour simplifier la procédure, il est possible de l’automatiser en la déclarant comme un "service" Linux, qui sera lancé au démarrage, et plus précisément dès le niveau d’exécution 2 ou 3, c’est à dire avant le lancement de l’interface graphique (niveau 5).
Le module étant bêtement copié à partir du répertoire des modules de l’ancien kernel, il faudra d’abord l’effacer dans le répertoire du nouveau kernel pour que l’installation automatique puisse s’effectuer au prochain démarrage.
nvidialibpath=$(find /usr/lib/modules/ -maxdepth 1 -mmin -10 | tail -n 1); # modifié il y a moins de 10 minutes = /usr/lib/modules + le sous dossier du nouveau kernel
est_present=$(find $nvidialibpath -iname "nvidia.ko" | grep -i "nvidia.ko" | wc -l);
if [ $est_present -gt 0 ]
then
echo "Le module nvidia.ko a été bêtement copié dans $nvidialibpath, on le nettoie pour que l'installation automatique puisse se faire au prochain démarrage";
find $nvidialibpath -iname "nvidia.ko" -exec rm -f {} \; # au pire, le script d'installation automatique peut le recréer
fi
Ce petit script, à lancer juste après une mise à jour du kernel, recherche les éléments modifiés il y a moins de 10 minutes dans le dossier /usr/lib/modules
, sans aller dans les sous-répertoires.
Le répertoire du nouveau kernel sera renvoyé, mais le répertoire des modules aussi, on ne prend donc que la dernière ligne avec le tail -n 1
Puis on utilise le même code que celui expliqué plus bas pour chercher le module et vérifier son existence.
Auquel cas on efface le module nvidia.ko
bêtement copié dans le répertoire des modules du nouveau kernel afin que le service d’installation/recompilation automatique du module nvidia puisse s’exécuter.
Le "service" est déclaré dans un fichier de /etc/init.d
#!/bin/bash
Ce fichier commence, comme tous les scripts, par faire référence à son environnement de commande.
# chkconfig: 23 99 10
On indique à chkconfig que ce service sera à démarrer aux niveaux 2 et 3, avec une priorité de démarrage de 99 (après tout le reste donc), et une priorité d’arrêt de 10 (sans importance, pas d’action d’arrêt pour ce service).
Les informations pour chkconfig
sont documentées dans le man de la commande
On indique ensuite quelques informations
# description: Recompile le pilote nvidia pour le noyau en cours si besoin
#
### BEGIN INIT INFO
# Provides: install_nvidia
# Default-Start: 2 3
# Default-Stop: 0 6
# Description: Recompile le pilote nvidia pour le noyau en cours si besoin
### END INIT INFO
Puis on initialise le script en lui même, en récupérant la version du noyau en cours, le chemin dans lequel est par conséquent sensé se trouver le module Nvidia pour la version du noyau Linux, avant de compter le nombre de modules présents.
rc=0;
nvidia_installer="NVIDIA-Linux-x86_64-375.20.run";
kernelver=$(uname -a | awk '{ print $3 }');
nvidialibpath="/usr/lib/modules/$kernelver";
est_present=$(find $nvidialibpath -iname nvidia.ko | grep -i nvidia.ko | wc -l);
logfile="/var/log/install_nvidia.log";
Comme tout service, on déclare une action "start", stop et status", à minima.
case "$1" in
start)
L’action "start" consistera à vérifier si le module est présent, et si non, lancer la ré-exécution du blob Nvidia.
Les sorties sont redirigées vers le fichier journal de l’installeur Nvidia.
Le blob Nvidia (ici NVIDIA-Linux-x86_64-346.35.run
, déposé dans /usr/local/src
) accepte un certain nombre d’options, dont :
-a
accepte automatiquement la licence.-s
lancement silencieux, sans question ni affichage, on suppose que toutes les réponses sont "oui" aux questions posées
nvidia-xconfig
-X
lancer nvidia-xconfig
à la fin de l’installation afin de configurer le fichier de configuration de l’interface graphique-h, --help, -A
pour afficher les différentes options, dont les options avancées.--update
se connecte automatiquement au serveur FTP de Nvidia et détermine puis télécharge et installe la dernière version du pilote.Le fichier exécutable doit avoir un certain nombre de droits et éventuellement le bon contexte SeLinux :
ls -Z /usr/local/src/NVIDIA-Linux-x86_64-346.35.run
-rwxr--r--. root root unconfined_u:object_r:usr_t:s0 /usr/local/src/NVIDIA-Linux-x86_64-346.35.run
retour au script du service :
echo "================================================================" >> $logfile;
echo "Lancement du script d'installation (ou pas) de NVidia le $(date)" >> $logfile;
echo "Le noyau Linux installé est $kernelver" >> $logfile;
echo "on cherche le module nvidia.ko dans $nvidialibpath" >> $logfile;
if [ $est_present -gt 0 ]
then
echo "Le module nvidia est présent dans $nvidialibpath" >> $logfile;
else
echo "Le module nvidia est absent, on le recompile" >> $logfile;
#/usr/local/src/NVIDIA-Linux-x86_64-346.59.run -a -s -X
#/usr/local/src/NVIDIA-Linux-x86_64-352.55.run -a -s -X
echo "On lance /usr/local/src/$nvidia_installer -a -s -X" >> $logfile;
IGNORE_CC_MISMATCH=1 /usr/local/src/$nvidia_installer -a -s -X 2>&1 >> $logfile
if [ $? -ne 0 ]
then
echo "On relance /usr/local/src/$nvidia_installer -a -s -X" >> $logfile;
IGNORE_CC_MISMATCH=1 /usr/local/src/$nvidia_installer -a -s -X 2>&1 >> $logfile
fi
if [ $? -eq 0 ]
then
echo "Tout s'est bien passé" >> $logfile;
echo "Mise à jour du paquet kmod-nvidia" >> $logfile;
dnf update kmod-nvidia* -y 2>&1 1>>$logfile
else
echo "La mise à jour du pilote NVidia s'est mal passée" >> $logfile;
fi
fi
rc=$?
;;
Ce service n’a pas d’action particulière pour son arrêt.
stop)
echo "Rien à faire, ce service est un lancement ponctuel au démarrage et non un démon.";
;;
L’action status se content d’indiquer si le module Nvidia est présent ou non.
status)
echo "Le noyau Linux installé est $kernelver";
echo "on cherche le module nvidia.ko dans $nvidialibpath";
if [ $est_present -gt 0 ]
then
echo "Le module nvidia est présent dans $nvidialibpath";
else
echo "Le module nvidia est absent de $nvidialibpath";
fi
;;
esac
exit $rc
Il faudra ensuite donner à ce script les droits d’exécution, ainsi que le propriétaire/groupe et éventuellement le contexte SeLinux
-rwxr-xr-x. root root unconfined_u:object_r:etc_t:s0 /etc/init.d/install_nvidia
Et enfin, on passera par systemctl
pour activer le service, systemctl
redirigera alors vers l’ancien "protocole" avec chkconfig
.
systemctl enable install_nvidia
Un systemctl status
permettra de voir si tout est bien paramétré.
systemctl status install_nvidia
install_nvidia.service - LSB: Recompile le pilote nvidia pour le noyau en cours si besoin
Loaded: loaded (/etc/rc.d/init.d/install_nvidia)
Active: active (exited) since ven. 2015-05-01 11:40:29 CEST; 1h 58min ago
Process: 1718 ExecStart=/etc/rc.d/init.d/install_nvidia start (code=exited, status=0/SUCCESS)
Un coup d’œil à la fin du fichier journal permettra de s’assurer que tout s’est bien passé.
On aurait pu ajouter au début du script un vidage ou une rotation de fichier journal afin de limiter sa taille.
Et la commande service - status
service install_nvidia status
Le noyau Linux installé est 3.19.5-100.fc20.x86_64
on cherche le module nvidia.ko dans /usr/lib/modules/3.19.5-100.fc20.x86_64
Le module nvidia est présent dans /usr/lib/modules/3.19.5-100.fc20.x86_64