blocage
Document Copyright © 1997-2011 Nat Makarevitch et les autres auteurs cités
La plus récente version de ce texte se trouve en http://wiki.linux-france.org/wiki/blocage.
Seule la diffusion des versions non modifiées est autorisée.
[modifier] Introduction
Ce texte en cours de rédaction peut permettre de découvrir pour quelle raison un programme ne fonctionne pas correctement.
Il ne s'agit ici que de dysfonctionnements "système", c'est-à-dire causés par un contexte d'exploitation donné et non à un algorithme inadéquat sur le plan fonctionnel (qui ne "fait pas" ce que l'on souhaite). Plus explicitement le présent document n'est pas un manuel de débogage mais plutôt description de ce que l'on peut faire afin de comprendre pourquoi un programme qui censé fonctionner ne le fait pas sur une machine donnée.
Notes : cette "checklist" n'abrite rien d'original et n'intéressera pas les utilisateurs confirmés.
[modifier] Checklist
[modifier] Fichiers de trace
Ne pas négliger que de nombreux programmes, au prix d'un paramétrage adéquat, enregistrent de façon plus ou moins complète et détaillée l'historique de leur activité dans des fichiers de traces (dits "log").
Ces derniers se trouvent le plus souvent sous le répertoire /var/log/.
"syslog" est le nom générique d'une famille de démons utilitaires auxquels tout programme peut à tout moment expédier un message révélateur de son activité. syslog désignera ici le démon utilisé, même si son nom n'est pas «syslog» (il peut s'agit de «rsyslog», de «dsyslog», «syslog-ng»...).
Le programme fournit à syslog, avec chaque message:
- le type de la mission concernée (un message relatif à la messagerie, par exemple, peut ainsi être donné pour tel). C'est peu utile car les types disponibles ne recouvrent pas le gros des besoins
- le niveau d'importance (le message est-il une simple information, un avertissement, une alerte...?)
syslog filtre chaque message, en fonction de son paramétrage, afin de déterminer ce qu'il doit écrire ou non et dans quel fichier de log le faire. On peut ainsi définir ce qu'il fera (le stocker ou non, où le stocker...) de tout message relevant d'un type (par exemple tout ce qui concerne la messagerie) ou d'un niveau d'importance (par exemple tout ce qui n'est pas au moins une alerte), ou contenant une chaîne donnée (par exemple tout message contenant "ProgrammeDeTest")...
Un démon syslog doit être actif. Pour vérifier :
ps auxw | grep syslog | grep -v grep
Cela doit produire une ligne ressemblant à ceci :
root 3224 0.0 0.0 1816 628 ? Ss 20:35 0:00 /sbin/syslogd
Si ce n'est pas le cas le système est étrangement configuré ou mal en point, tenter d'installer le paquet nommé «sysklogd».
Admettons qu'un "syslog" est installé et actif.
Explorez la configuration/paramétrage de votre syslog:
- noms complets (avec chemin d'accès) des fichiers de log
- filtres (qui ne doivent pas de ligne de log potentiellement révélatrice de la cause du blocage)
Certains programmes ne confient pas tous leurs logs à syslog. Lire leurs documentations afin de déterminer :
- s'ils délèguent la gestion de ses traces à "syslog" et/ou s'ils s'en chargent (certains délèguent partiellement: des éléments d'historique sont confiés à syslog tandis que d'autres sont directement écrits dans des fichiers par le programme),
- la configuration et/ou les options d'invocation les invitant à produire des traces détaillées
[modifier] En pratique
Dans un terminal saisir, en tant que root, la commande suivante (ne pas l'invoquer):
find /var/log -type f -mmin -1
Dans un autre terminal invoquer le programme défectueux, si possible en mode debug et verbose (lire sa doc et son man, puis revenir immédiatement au terminal root et invoquer la commande. Elle produira la liste des noms des fichiers de traces modifiés durant la minute écoulée. Les examiner grâce à less ou à grep afin de trouver des indices, par exemple en cherchant le nom du programme, ou des fichiers qu'il traite...
Si peu de lignes de log décrivent l'activité du programme posant problème vérifier les règles de filtrage des messages par "syslog". Elles sont établies par l'administrateur car il n'est généralement pas nécessaire de consigner tous les logs dans le fichier de log. Si la machine emploie le démon "syslogd", par exemple, le fichier /etc/syslog.conf recèle ces règles. Pour que "syslog" enregistre tout durant la résolution du problème il suffit de le conserver puis temporairement remplacer par une version consignant tout:
*.* /var/log/total_temporaire.log
Puis de demander au démon de relire sa configuration (sous Debian invoquer /etc/init.d/sysklogd reload). Tenter alors de nouveau les manoeuvres ne donnant pas satisfaction comme déjà décrit (debug et verbose). Une fois le problème résolu restaurer les paramètres de syslog et les lui faire relire.
[modifier] Environnement
[modifier] Langue
Relancer le programme après avoir invoqué (sur ligne de commande):
LANG=CTODO; expliquer
[modifier] S'informer
Consulter Google puis le site Web du logiciel (la documentation contient souvent son URL), en y cherchant des termes du message d'erreur.
Tenter de grouper les termes les plus significatifs et d'en extraire ce qui est vraisemblablement dépendant du contexte. Par exemple lorsque le programme nommé example produit le message "Syntax error line 4242: I need a variable name!" chercher ceci (guillemets inclus):
+example "Syntax error line" "I need a variable name!"
Si les résultats sont contradictoires limiter la recherche au site web le plus pertinent. Pour cela chercher le nom de nom de domaine IP du site web du projet (par exemple example.org) puis le fournir préfixé de site: . Exemple:
site:example.org "Syntax error line" "I need a variable name!"
[modifier] Cerner le problème
Tester diverses options, modes de fonctionnement, données à traiter afin de déterminer ce qui fonctionne ... ou pas. S'assurer que l'on dispose bien d'espace-disque (commande df), que les répertoires temporaires (/tmp, /var/tmp ...) ne sont pas saturés, essayer après mise à zéro de toutes les variables d'environnement douteuses (utiliser printenv pour les examiner et, sous bash, export NOM_VARIABLE= pour les supprimer.
Si le programme crashe sur réception d'un "signal 11" (dit "SIGSEGV") lire la FAQ signal 11
[modifier] Analyser les messages d'erreur
Dériver au besoin le canal de sortie standard et celui réservé aux erreurs vers un fichier. Invoquer pour cela (sous bash) :
nom_du_programme 2>&1 | tee nom_du_programme.sortie.tmp
Les messages (y compris d'erreur) du programme seront stockés (par tee) dans le fichier nommé nom_du_programme.sortie.tmp.
Si le programme est un script de shell l'invoquer en mode trace. Exemple (sous bash) :
bash -x nom_du_programme 2>&1 | tee nom_du_programme.sortie.tmp
[modifier] Lecture, par le programme, de ses fichiers de configuration
Déterminer comment vérifier que le programme lit et interprète correctement le contenu de ses fichiers de configuration. Pour cela chercher comment lui faire produire quelque part (dans un fichier de log, sur son stdout...) ses paramètres de fonctionnement. Il suffit parfois de lui passer un/des argument ou paramètre le faisant fonctionner en mode debug et verbose, ou de le contraindre à montrer (dump) ses paramètres...
En désespoir de cause tenter d'employer strace (lire ci-après): strace -s0 -eopen,read NomDuBinaire
[modifier] Mise à jour
Installer la plus récente version du logiciel.
[modifier] Bien lire sa documentation
En théorie mieux vaudrait toujours commencer par cela, mais les habitudes d'empirisme contractées... Bref.
Ne pas oublier les pages de manuel. Sous Debian explorer /usr/share/doc/nom_du_programme*.
S'assurer que tous les composants requis (bibliothèques, éditeur de liens dynamiques, serveur X ...) sont bien installés.
[modifier] Fichiers de verrouillage (lock)
En cas de problème de partage de ressources surveiller le contenu de /var/lock durant les essais.
[modifier] Utiliser un traceur d'appels
Lancer le programme sous "strace". Cet outil dresse, au fur et à mesure de l'exécution d'un binaire, liste des appels à la bibliothèque système (la fameuse libc).
Exemple : lorsque le programme fonctionne bien si root l'emploie mais mal sinon on pourra comparer ainsi les contextes :
su - # passer root cd /tmp touch fichier_sans_interet chown root.root fichier_sans_interet chmod g=,o= fichier_sans_interet strace -s80 -oessai_root.tmp cat fichier_sans_interet chmod a+r essai_root.tmp exit # retour sous un compte utilisateur non privilégié cd /tmp strace -s80 -oessai_user.tmp cat fichier_sans_interet # le message d'erreur apparaît, il est facile à comprendre. mais # comportons-nous comme si "cat" n'en produisait pas ... diff essai_user.tmp essai_root.tmp | tail -50
Un certain nombre de lignes apparaissent. L'une d'elle révèle de façon claire la cause du problème :
< open("fichier_sans_interet", O_RDONLY) = -1 EACCES (Permission denied)
Il suffit de lire la page de manuel de la fonction "open" pour comprendre que le processus de l'utilisateur non root a tenté d'ouvrir le fichier nommé fichier_sans_interet en mode "lecture seule" (O_RDONLY : Open ReaD-ONLY), ce que le système lui refusa en renvoyant un code de retour -1 (permissions inadéquates).
L'option -f, grâce à laquelle "strace" piste tous les processus créés par le programme examiné, est souvent utile.
"strace" peut aussi « espionner » un processus actif grâce à son option -p. Pour aller plus loin utiliser ensuite "ltrace".
[modifier] lsof
TODO
[modifier] Stockage (disque...)
atop et iotop
TODO
[modifier] Réseau
[modifier] netstat
(sous BSD: sockstat)
TODO
[modifier] iptraf
TODO
[modifier] Recompiler
Recompiler, car certains sources de programmes (surtout des utilitaires) créent des binaires dépendants de la version du noyau utilisé lors de leur compilation.
Recompiler sans optimisations (cas de gcc: pas de "-m..." ni de "-O...").
[modifier] Debogage
Pourquoi, si vous connaissez un peu le langage utilisé par les développeurs du programme, ne pas essayer de déterminer la cause du problème ?
S'il s'agit d'un programme en C ou C++ et que vous connaissez le langage:
- le compiler (de préférence avec --prefix=/usr/local) en mode "debug" afin que le binaire intègre des informations associant chaque ligne du code source au petit morceau d'exécutable correspondant (euh ... c'est un peu simplifié). Cas du C / C++ : il suffit souvent d'ajouter "-ggdb" dans les options passées à gcc, ce qui s'effectue d'ordinaire en ajoutant ce paramètre au CFLAGS du Makefile. En cas de crash violent (message Segmentation fault) autoriser la production de fichiers core grâce à ulimit -c 0 (explications : chercher ulimit dans le man de bash), faire crasher la version compilée en mode debug, invoquer 'gdb nomdubinaire core', puis utiliser la commande 'where'.
- installer cette version de debogage ("make install")
- invoquer le binaire, le placer dans les conditions dans lesquelles il "se plante". Cela doit produire une image ("core dump"), sous forme d'un fichier nommé "core"
- installer "gdb" puis invoquer "gdb -d nom_du_répertoire_abritant_les_sources nom_du_binaire core"
- introduire "where"
[modifier] Plantages 'aléatoires' ou 'bizarres'
Voici ma recette personnelle (et néanmoins brutale). Il faut essayer d'exploiter la machine entre chacune des étapes proposées et conserver, étape après étape, les modifications opérées.
- lire et étudier les messages des programmes et des logs (configurer temporairement
syslogde sorte qu'il conserve trace de tout), en particulier du noyau. Ils se trouvent d'ordinaire dans /var/log/kernel, et la commande dmesg offre moyen de paramétrer et de consulter les messages produits par le noyau - vérifier que les programmes ne manquent pas de mémoire (commandes "free", "top" ...)
- lire la FAQ SIG 11.
- examiner
/proc/pci,/proc/interruptset/proc/dmaainsi que les configs des cartes installées (config matérielle (sur la carte), logicielle (utilitaire spécifique livré par le constructeur, employer la plus récente version), afin de détecter un conflit - cesser d'employer "hdparm" (restaurer ses paramètres par défaut ou le désinstaller, puis réamorcer)
- réduire la fréquence du CPU (certains escrocs vendent des processeurs conçus pour fonctionner X MHz en tant que X+quelquechose MHz) et du bus (composants de mémoire vive inadéquats)
- renoncer temporairement à la mémoire virtuelle ("swap") : la mettre hors ligne (commande "swapoff"), réessayer, puis la reformater ("mkswap") avant ré-emploi
- déposer toutes les cartes d'extension non strictement nécessaires
- mettre hors fonction tout code (BIOS, module du système d'exploitation, démons, logiciels applicatifs ...) liés à l'APM ou à l'ACPI (gestion de l'énergie)
- installer un noyau compilé sans options inhabituelles et pour le processeur le plus classique (cas des PC: 386)
- restaurer les paramètres par défaut du BIOS (grâce au SETUP)
- paramètres BIOS: débrayer tous les "shadows" et caches
- se procurer et installer la plus récente version du BIOS (firmware) disponible
- installer des bibliothèques et outils (libc, gcc, ld.so, gcc ...) stables, puis recompiler les programmes
- changer de clavier (oui, oui, je sais, c'est dément. mais en fait non :-) )
- déposer la moitié des composants (barettes) de RAM
- déposer la moitié de RAM encore montée, monter l'autre en lieu et place
- ne monter que le minimum de RAM, essayer ainsi avec toutes les barettes
- changer l'emplacement (
slot) des cartes d'extension - changer d'alimentation électrique (de prise « secteur »)
- éteindre tous les appareils électriques environnants (surtout les plus consommateurs ou ceux dont le fonctionnement est très heurté)
- changer d'alimentation électrique (l'alim à découpage, dans la machine)
- changer de disque dur
- changer de CPU
- changer de carte mère
- acheter une autre machine complète (cartes d'extension comprises)
- essayer l'hypoaristerolactothérapie : méthode de dépannage des machines par le coup de pied en bas à gauche (selon Michel Dubesset).
- renoncer à l'informatique, puisqu'elle tente manifestement de vous plaquer
[modifier] No space left on device
Vérifier, grâce à la commande df, l'espace disponible sur le système de fichiers.
Déterminer si l'utilisateur root parvient ou non à utiliser de l'espace de stockage. Si c'est le cas: l'espace disponible correspond peut-être au seul pourcentage de blocs réservés à l'utilisateur root, défini par paramètre "-m" de nombreux outils de création de système de fichiers (lire par exemple "man mkfs.ext2"). En ce cas il faut détruire des fichiers.
Déterminer s'il est possible de créer un fichier. Si ce n'est pas le cas vérifier grâce à "df -i" le nombre d'inodes disponibles. En cas de saturation il faut détruire des fichiers.
[modifier] Démontage d'un système de fichiers impossible
En cas de message "device is busy" il faut déterminer quels programmes emploient le système de fichier. Invoquer pour cela fuser -c SonNom (où SonNom est celui du device ou du répertoire de montage): les PID concernés apparaissent (chacun suivi d'un ou plusieurs caractères, que vous négligerez à ce stade). Utiliser ps afin de déterminer quel programme animent ces processus, les arrêter et démonter.
[modifier] Lenteur
Vérifier la fréquence du CPU:
grep MHz /proc/cpuinfo
[modifier] Bloqué dans un terminal (ligne de commande ou console)
Composer Control-q (maintenir la touche Contrôle ou Ctrl et enfoncer la touche Q puis )
reset console
[modifier] Bloqué sous un éditeur
[modifier] Déterminer le nom de l'éditeur
TODO
[modifier] Bloqué sous X Window (interface graphique)
TODO: passer en console, reset chipset