blocage

De Linux France
Aller à : navigation, rechercher

Introduction[modifier]

À propos de ce document[modifier]

Copyright © 1997-2014 Nat Makarevitch et les autres auteurs cités

La plus récente version de ce texte est publiée en http://wiki.linux-france.org/wiki/blocage.

Seule la diffusion des versions non modifiées est autorisée.

Objet[modifier]

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 est censé fonctionner, idéalement qui a déjà fonctionné ou fonctionne ailleurs, ne le fait pas (ou plus, ou pas toujours) sur une machine donnée.

Notes : cette "checklist" n'abrite rien d'original et n'intéressera pas les utilisateurs confirmés.

Un autre article décrit la « ligne de commande » (les commandes fondamentales).

Checklist[modifier]

S'informer[modifier]

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!"

Fichiers de trace[modifier]

De nombreux programmes, au prix d'un paramétrage adéquat, rendent compte de façon plus ou moins complète et détaillée de leur activité dans des fichiers de traces (dits "log") qui se trouvent le plus souvent sous le répertoire /var/log/.

Ils sont gérés par un démon utilitaire de type "syslog", nom générique d'une famille de logiciels auxquels tout programme peut à tout moment expédier un message révélateur de son activité. Ce message connaît le sort défini par l'administrateur (grâce à un fichier de paramétrage): déclenchement d'une alerte, archivage pour consultation ultérieure, destruction s'il n'est pas jugé intéressant...

syslog désignera ici le démon utilisé, même si son nom n'est pas «syslog» (il peut s'agir de «rsyslog», «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 sont prédéfinis et ceux qui le sont par les syslogs classiques ne recouvrent pas le gros des besoins contemporains
le niveau d'importance
le message est-il une simple information, un avertissement, une alerte...?

syslog, en fonction de ses paramètres, filtre chaque message afin de déterminer ce qu'il doit écrire ou non et dans quel fichier de log le faire. On peut ainsi paramétrer son comportement (stocker ou non un message, où le stocker...) selon le type du message (par exemple s'il concerne la messagerie), de son niveau d'importance (par exemple tout ce qui n'est pas au moins une alerte) voire de son contenu (par exemple tout message contenant "ProgrammeDeTest").

Un démon syslog ne nous aidera que s'il est actif actif. Pour déterminer si c'est le cas :

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 son paramétrage afin de connaître:

  • noms complets (avec chemin d'accès) des fichiers de log
  • filtres (qui doivent mener au stockage dans un fichier de tout message de log potentiellement révélateur de la cause du blocage)

Ce paramétrage est établi par root et se trouve, si la machine emploie le démon "rsyslogd", dans le fichier /etc/rsyslog.conf (examiner aussi un éventuel répertoire /etc/rsyslogd.conf). Pour que "syslog" enregistre tout durant la résolution du problème il suffit de conserver ce/ces fichiers de paramètres et de les remplacer temporairement par une version consignant tout donc contenant en tout et pour tout:

*.*                 /var/log/total_temporaire.log

Demander au démon de relire sa configuration (sous Debian invoquer /etc/init.d/sysklogd reload). Tenter alors de nouveau les manœuvres ne donnant pas satisfaction comme déjà décrit (debug et verbose).

ATTENTION: sitôt le problème résolu restaurer les paramètres de syslog et les lui faire relire, sous peine d'enregistrer inutilement beaucoup de logs donc de ralentir la machine et de risquer de saturer un système de fichiers.

Certains programmes ne confient pas tous leurs logs à syslog. Lire la documentation afin de déterminer :

  • si le programme délègue la gestion de ses traces à "syslog" et/ou s'il s'en charge (certains délèguent partiellement: des éléments d'historique sont confiés à syslog et le programme en écrit directement d'autres),
  • la configuration et/ou les options d'invocation les invitant à produire des traces détaillées

En pratique[modifier]

Dans un terminal saisir, en tant que root, la commande suivante:

tail -F /var/log/*.log

Cela nous montrera à mesure les ajouts dans les seuls fichiers de log d'extension ".log"

Dans un autre terminal s'assurer que syslog et son paramétrage sont adéquats. Utiliser pour cela un programme offrant moyen de lui expédier un message, par exemple « logger ». Invoquer par exemple:

logger -p mail.debug test de Nat

Préparer ensuite la commande suivante (ne pas appuyer sur la touche « Entrée », nous la préparerons ici en vue d'une invocation ultérieure):

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 montrant les logs et lire ceux qui apparurent.

Retourner au terminal précédent afin d'obtenir la liste des noms des fichiers de traces modifiés durant la minute écoulée, en validant:

find /var/log -type f -mmin -1

Examiner le contenu de tout fichier modifié grâce à tail, et si nécessaire à less et grep, afin de trouver des indices, par exemple en cherchant le nom du programme ou des fichiers qu'il traite.

Si peu de noms de fichiers apparaissent, alors 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".

Sitôt cette surveillance des logs activées la garder en fonction durant toute la séance de déblocage, et y revenir périodiquement en quête d'indices.

Note: divers outils assurent aussi automatiquement que possible cette veille, par exemple en vous expédiant périodiquement un courriel recelant celles des lignes de log qui sont inhabituelles ou non déclarées (par vous ou par les éditeurs de la distribution) « normales ». Il s'agit par exemple de logcheck, Logwatch

Environnement[modifier]

Langue[modifier]

Relancer le programme après avoir invoqué (sur ligne de commande):

export LANG=C

TODO: expliquer

Le programme produira peut-être alors des messages d'erreur en anglais. Les chercher sur le Web.

Cerner le problème[modifier]

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

Analyser les messages d'erreur[modifier]

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

Vérifier bonne lecture de tout fichier de configuration[modifier]

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

Installation[modifier]

Vérifier les horloges[modifier]

Tous les systèmes concernés, clients comme serveurs, doivent être à l'heure, pas de retard ou d'avance trop élevé. NTP est ton ami.

Compléter l'installation[modifier]

S'assurer que tous les composants requis (bibliothèques, éditeur de liens dynamiques, serveur X ...) sont bien installés (un paquet manque peut-être). Sous Debian et assimilés:

aptitude install -f

Mise à jour ou réinstallation[modifier]

Installer la plus récente version du logiciel. Vérifier au préalable qu'elle correspond au besoin.

Sous Debian et assimilés:

dpkg -S NomCompletDuProgramme # afin de trouver le nom du paquet recelant le programme
sudo aptitude update
sudo aptitude reinstall NomDuPaquet

Réinstallation des dépendances[modifier]

Réinstaller tous les paquets dont il dépend (voire ceux dont ces derniers dépendent...), parfois endommagés par une installation d'archive publiée par un constructeur (cas fréquent avec les imprimantes, scanners...).

Pour obtenir liste de ce dont dépend un paquet:

apt-cache --no-recommends --no-suggests --no-conflicts --no-breaks --no-replaces --no-enhances depends NomDuPaquet

Vérification d'intégrité[modifier]

Vérifier l'intégrité des fichiers déployés, par exemple (Debian et assimilés) grâce à « debsums »:

sudo debsums -c # Debian et assimilés
rpm -V # distributions de la famille RPM

Mise à jour globale[modifier]

Au pis tenter une mise à jour de l'ensemble des logiciels, mais c'est dangereux car peut arrêter certains services ou exiger des heures d'adaptation de fichiers de configuration. Debian et assimilés:

sudo aptitude update
sudo aptitude safe-upgrade # DANGER
sudo aptitude full-upgrade # ENCORE PLUS DANGEREUX

Bien lire sa documentation[modifier]

En théorie mieux vaudrait toujours commencer par cela, mais le trop habituel empirisme... Bref.

Sous Debian explorer /usr/share/doc/nom_du_programme*.

Ne pas oublier les pages de manuel, et aussi la commande apropos à laquelle fournir en argument des mots-clés pertinents. Si j'ai un problème avec une horloge j'invoque apropos clock qui liste les pages de manuel probablement pertinentes. Sur un système où le man est en français écrire horloge au lieu de clock!

Fichiers de verrouillage (lock)[modifier]

En cas de problème de partage de ressources surveiller le contenu de /var/lock durant les essais.

Utiliser un traceur d'appels[modifier]

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".

Examiner les ressources utilisées[modifier]

TODO : lsof & co

Stockage (disque...)[modifier]

Qui lit/écrit sur une unité de stockage (« disque »)?[modifier]

Il s'agit ici des seuls accès au périphérique, pas des demandes satisfaites par un cache.

iotop -o -b -qqq

Réseau[modifier]

netstat[modifier]

(sous BSD: sockstat)

TODO

iptraf[modifier]

TODO

Recompiler[modifier]

Recompiler, car certains sources de programmes (surtout des utilitaires) créent des binaires dépendant de la version du noyau utilisé lors de leur compilation.

Recompiler sans optimisations (cas de gcc: pas de "-m..." ni de "-O...").

Debogage[modifier]

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"

Cas classique[modifier]

No space left on device[modifier]

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.

Démontage d'un système de fichiers impossible[modifier]

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.

Lenteur[modifier]

Vérifier la fréquence du CPU:

grep MHz /proc/cpuinfo

Bloqué dans un terminal (ligne de commande ou console)[modifier]

Composer Control-q (maintenir la touche Contrôle ou Ctrl et enfoncer la touche Q puis )

reset console

Bloqué sous un éditeur[modifier]

Déterminer le nom de l'éditeur[modifier]

TODO

Bloqué sous X Window (interface graphique)[modifier]

TODO: passer en console, reset chipset

Plantages 'aléatoires' ou 'bizarres'[modifier]

Il s'agit ici du cas d'un problème vraisemblablement causé par du matériel inadéquat ou défectueux.

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 syslog de 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/interrupts et /proc/dma ainsi 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 paramètre ou 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 :-) )
  • installer les utilitaires memtest86 et memtest86+, puis les lancer durant au moins 12 heures chacun
  • 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