208 codes sur 208
L'opération exige des privilèges que le processus n'a pas, comme changer le propriétaire d'un fichier, envoyer un signal à un processus d'un autre utilisateur ou modifier un fichier immuable (chattr +i). Contrairement à EACCES, cela ne se résout pas en changeant les permissions du fichier : il faut être root ou disposer de la capability correspondante.
Le fichier ou le répertoire n'existe pas. Apparaît aussi lorsqu'il manque un répertoire intermédiaire du chemin, lorsqu'un lien symbolique pointe vers une cible qui n'existe pas ou lorsque l'interpréteur de la ligne #! d'un script n'est pas installé.
Il n'existe aucun processus, groupe de processus ou thread avec cet identifiant ; par exemple, lors d'un kill sur un PID déjà terminé.
Un signal a interrompu l'appel système avant qu'il ne se termine. Ce n'est pas une vraie erreur : le programme doit relancer l'appel, ou installer le gestionnaire du signal avec SA_RESTART.
Erreur d'entrée/sortie de bas niveau, en général lors de la lecture ou de l'écriture sur le périphérique. Sur les disques, elle indique souvent des secteurs défectueux ou un câble défaillant : vérifiez dmesg et l'état SMART. Apparaît aussi lors de l'écriture sur un terminal déjà fermé.
Le périphérique ou l'adresse n'existe pas : le fichier de périphérique est présent, mais aucun matériel ne se trouve derrière, ou un FIFO a été ouvert en écriture avec O_NONBLOCK sans aucun lecteur.
La liste des arguments et des variables d'environnement passée à exec est trop grande. C'est le classique « Argument list too long » lorsqu'on utilise un joker qui s'étend à des milliers de fichiers ; utilisez find -exec ou xargs.
Le fichier n'a pas de format exécutable reconnu : c'est un binaire d'une autre architecture, il est endommagé ou c'est un script sans ligne #!.
Le descripteur de fichier n'est pas valide, a déjà été fermé ou a été ouvert dans un mode qui ne permet pas l'opération, comme écrire dans un descripteur ouvert en lecture seule.
Le processus n'a aucun enfant à attendre avec wait ou waitpid, souvent parce que SIGCHLD est ignoré et que les enfants sont récupérés automatiquement.
La ressource n'est pas disponible pour le moment et il vaut mieux réessayer. Dans les opérations non bloquantes, cela signifie qu'il n'y a pas encore de données ou d'espace ; avec fork, que la limite de processus ou de threads a été atteinte (ulimit -u ou pids.max du cgroup).
Même valeur :EWOULDBLOCK
Il n'y a pas assez de mémoire pour l'opération ou une limite de mémoire du processus a été dépassée. Avec fork ou mmap, cela peut venir de la politique d'overcommit, de la limite du cgroup ou du manque d'espace d'adressage.
Permission refusée par les permissions du fichier ou d'un répertoire du chemin (il faut la permission d'exécution sur chacun), par une ACL, par SELinux ou AppArmor, ou par un montage avec noexec. bind le renvoie aussi lorsqu'on utilise un port inférieur à 1024 sans privilèges.
Un pointeur vers une adresse mémoire non valide a été passé à un appel système. Cela indique un bug dans le programme.
L'opération nécessite un périphérique bloc, comme un disque, et a reçu un autre type de fichier ; par exemple, lors du montage d'un fichier ordinaire sans -o loop.
Le périphérique ou la ressource est occupé. C'est typique lors du démontage d'un système de fichiers qui a des fichiers ouverts ou un terminal positionné dessus ; lsof ou fuser montrent quels processus l'utilisent.
Un fichier, un répertoire ou un autre objet portant ce nom existe déjà, par exemple lors d'une création avec O_EXCL, avec mkdir sans -p ou lors de la création d'un lien dont la cible existe déjà.
Impossible de créer un lien physique ou de renommer un fichier entre des systèmes de fichiers différents. mv le résout en copiant puis en supprimant ; les programmes qui utilisent rename() doivent faire de même.
Le périphérique n'existe pas ou ne prend pas en charge l'opération ; par exemple, lors du montage d'un type de système de fichiers dont le module du noyau n'est pas chargé.
Un composant du chemin qui devrait être un répertoire est un fichier, ou un répertoire a été demandé (O_DIRECTORY) et ce n'en est pas un.
Une opération de fichier a été tentée sur un répertoire, comme l'ouvrir en écriture.
Un argument n'est pas valide pour l'appel : une valeur hors limites, une combinaison d'options incompatible ou une opération que l'objet ne prend pas en charge. C'est générique : la page man de l'appel liste les cas concrets.
La table des fichiers ouverts de tout le système est épuisée. La limite se règle avec fs.file-max dans sysctl.
Le processus a atteint sa limite de descripteurs ouverts (« Too many open files »). Augmentez la limite avec ulimit -n ou avec LimitNOFILE dans systemd, et vérifiez que le programme ne laisse pas de fichiers ou de sockets ouverts.
Une opération de terminal (ioctl) a été demandée sur quelque chose qui n'est pas un terminal, par exemple lorsque la sortie d'un programme interactif est redirigée vers un fichier ou un pipe.
L'exécutable est en cours d'utilisation : on ne peut pas écrire dans un binaire pendant son exécution, ni exécuter un binaire encore ouvert en écriture. Pour le mettre à jour, il vaut mieux écrire un nouveau fichier et le renommer.
Le fichier dépasse la taille maximale prise en charge par le système de fichiers (4 Go en FAT32) ou la limite RLIMIT_FSIZE du processus.
Il ne reste plus d'espace sur le périphérique. Si df affiche de l'espace libre, vérifiez les inodes avec df -i. inotify le renvoie aussi lorsque fs.inotify.max_user_watches est épuisé.
Impossible de faire un lseek sur un pipe, un FIFO ou un socket, car ils n'ont pas de position.
Le système de fichiers est monté en lecture seule. S'il est passé en lecture seule sans que personne ne l'ait demandé, c'est le noyau qui l'a fait en détectant des erreurs : vérifiez dmesg et lancez fsck.
Le nombre maximal de liens physiques vers un fichier a été dépassé, ou celui des sous-répertoires d'un répertoire dans certains systèmes de fichiers.
Écriture dans un pipe ou un socket dont l'autre extrémité est déjà fermée (« Broken pipe »). En plus de l'erreur, le processus reçoit SIGPIPE ; c'est normal lorsque le lecteur se termine avant, comme dans cmd | head.
L'argument d'une fonction mathématique est hors de son domaine, comme la racine carrée d'un nombre négatif.
Le résultat d'une fonction est trop grand ou trop petit pour être représenté, ou un tampon est insuffisant pour le résultat, comme avec getcwd et un tampon trop court.
Un interblocage a été évité : le verrou demandé, comme un verrou de fichier avec fcntl ou un mutex avec détection d'erreurs, aurait attendu indéfiniment.
Même valeur :EDEADLOCK
Le chemin ou l'un de ses composants dépasse la longueur maximale : sous Linux, en général, 255 octets par nom et 4096 par chemin.
Aucun verrou disponible. Sur NFS, cela indique souvent que le service de verrouillage (lockd ou rpc.statd) ne fonctionne pas.
L'appel système n'existe pas dans ce noyau ou n'est pas implémenté. C'est typique des binaires compilés pour un noyau plus récent, ou des profils seccomp de conteneurs qui ne connaissent pas les appels récents.
Le répertoire n'est pas vide, par exemple avec rmdir ou lors d'un renommage par-dessus un répertoire existant. Pour le supprimer avec son contenu, utilisez rm -r.
Trop de liens symboliques enchaînés lors de la résolution du chemin, généralement à cause d'une boucle, ou O_NOFOLLOW a été utilisé sur un lien symbolique.
Aucun message du type demandé dans la file de messages System V.
L'identifiant IPC System V (file, sémaphore ou mémoire partagée) a été supprimé pendant que le processus l'utilisait.
Numéro de canal hors limites. C'est un code hérité sans usage pratique sous Linux.
Niveau 2 non synchronisé. C'est un code hérité de System V sans usage pratique sous Linux.
Niveau 3 arrêté. C'est un code hérité de System V sans usage pratique sous Linux.
Niveau 3 réinitialisé. C'est un code hérité de System V sans usage pratique sous Linux.
Numéro de lien hors limites. C'est un code hérité sans usage pratique sous Linux.
Le pilote du protocole n'est pas attaché. Peu de sous-systèmes l'utilisent, comme certains pilotes Bluetooth.
Aucune structure CSI disponible. C'est un code hérité sans usage pratique sous Linux.
Niveau 2 arrêté. C'est un code hérité de System V sans usage pratique sous Linux.
Échange non valide. C'est un code hérité que certains pilotes et systèmes de fichiers réutilisent avec un sens propre.
Descripteur de requête non valide. C'est un code hérité que certains pilotes réutilisent avec un sens propre.
Échange plein. C'est un code hérité sans usage pratique sous Linux.
Aucun « anode ». C'est un code hérité sans usage pratique sous Linux.
Code de requête non valide. C'est un code hérité ; certains pilotes l'utilisent pour les commandes qu'ils ne prennent pas en charge.
Slot non valide. C'est un code hérité sans usage pratique sous Linux.
Format de fichier de police incorrect. C'est un code hérité sans usage pratique sous Linux.
Le périphérique n'est pas un STREAM. Appartient à l'interface STREAMS de System V, que Linux n'implémente pas.
Aucune donnée disponible. Sous Linux, getxattr le renvoie lorsque l'attribut étendu n'existe pas ; sous macOS, ce cas correspond à ENOATTR.
Un temporisateur a expiré. Vient de STREAMS ; sous Linux, certains pilotes et io_uring l'utilisent pour les opérations avec délai.
Plus de ressources STREAMS, une interface que Linux n'implémente pas.
La machine n'est pas sur le réseau. C'est un code hérité peu utilisé.
Le paquet n'est pas installé. C'est un code hérité ; certains sous-systèmes l'utilisent lorsqu'un module manque, par exemple un module cryptographique.
L'objet est distant. Sur NFS, il indique un chemin exporté depuis un autre serveur.
Le lien a été coupé. C'est un code hérité ; certains pilotes l'utilisent lorsque la connexion avec le périphérique est perdue.
Erreur « advertise ». C'est un code hérité de RFS sans usage sous Linux.
Erreur « srmount ». C'est un code hérité de RFS sans usage sous Linux.
Erreur de communication lors de l'envoi. C'est un code hérité ; certains pilotes réseau et USB l'utilisent.
Erreur de protocole : l'autre extrémité ou le périphérique a répondu quelque chose d'inattendu. Apparaît avec des périphériques USB et dans des connexions coupées au milieu d'un échange.
Un saut multiple (multihop) a été tenté. C'est un code hérité de RFS.
Erreur spécifique à RFS. Sans usage sous Linux.
Le message est mal formé ou corrompu. ext4, XFS et Btrfs le renvoient, avec l'alias EFSBADCRC, lorsque la somme de contrôle des métadonnées échoue.
Même valeur :EFSBADCRC
La valeur ne tient pas dans le type de données de destination ; par exemple, un programme 32 bits compilé sans prise en charge des gros fichiers qui ouvre un fichier de plus de 2 Go.
Le nom n'est pas unique sur le réseau. C'est un code hérité.
Le descripteur de fichier est dans un état incorrect. ALSA et certains pilotes l'utilisent lorsque le périphérique n'est pas prêt.
L'adresse distante a changé. C'est un code hérité.
Impossible d'accéder à une bibliothèque partagée nécessaire. C'est un code hérité des binaires a.out.
La bibliothèque partagée est endommagée. C'est un code hérité des binaires a.out.
La section .lib du binaire a.out est endommagée. C'est un code hérité.
Tentative de lier trop de bibliothèques partagées. C'est un code hérité de a.out.
Une bibliothèque partagée ne peut pas être exécutée directement. C'est un code hérité de a.out.
La séquence d'octets n'est pas valide pour l'encodage de caractères, comme un texte qui n'est pas de l'UTF-8 valide lors de sa conversion avec iconv ou avec les fonctions multioctets.
L'appel interrompu doit être relancé. Il est réservé à l'usage interne du noyau et ne devrait pas parvenir aux programmes.
Erreur de pipe STREAMS. ALSA le renvoie lorsque le périphérique audio est suspendu.
Trop d'utilisateurs. Le système de quotas de disque le renvoie lorsque sa table est pleine, ce qui est rare.
Une opération de socket a été utilisée sur un descripteur qui n'est pas un socket.
L'adresse de destination manque : un envoi a été fait sur un socket non connecté sans indiquer où.
Le message est trop grand pour le socket, comme un datagramme UDP plus grand que le maximum ou que la MTU lorsque la fragmentation n'est pas autorisée.
Le protocole ne correspond pas au type de socket.
L'option de socket ou le protocole demandé n'est pas disponible, par exemple une option de setsockopt que le noyau ne connaît pas.
Le protocole n'est pas pris en charge, par exemple parce que son module du noyau n'est pas chargé.
Le type de socket n'est pas pris en charge dans cette famille d'adresses.
L'opération n'est pas prise en charge par le socket ou par l'objet. Sous Linux, il a la même valeur que ENOTSUP, et de nombreux systèmes de fichiers le renvoient pour des fonctions qu'ils n'implémentent pas, comme fallocate ou les attributs étendus.
L'opération n'est pas prise en charge. Sous Linux, il a la même valeur que EOPNOTSUPP (95) ; sous macOS, ce sont des codes distincts.
La famille de protocoles n'est pas prise en charge.
La famille d'adresses n'est pas prise en charge ; c'est typique lorsqu'on utilise IPv6 sur un système ou un conteneur où il est désactivé.
L'adresse et le port sont déjà utilisés : un autre processus écoute sur ce port, ou la connexion précédente est encore en TIME_WAIT. Trouvez le processus avec ss -ltnp ou lsof -i :PORT, ou utilisez SO_REUSEADDR.
Impossible d'attribuer l'adresse demandée : l'IP n'appartient à aucune interface de la machine, ou les ports éphémères pour les connexions sortantes sont épuisés.
L'interface réseau est inactive.
Le réseau de destination est inaccessible car il n'existe aucune route vers lui. Vérifiez la table de routage et la passerelle ; cela arrive aussi lors d'une connexion en IPv6 sans connectivité IPv6.
Le réseau a réinitialisé la connexion, par exemple lorsqu'un keepalive échoue.
La connexion a été interrompue du côté local, par exemple parce que le client l'a fermée avant que le serveur ne l'accepte avec accept.
L'autre extrémité a coupé brutalement la connexion avec un RST (« Connection reset by peer ») : le processus distant s'est fermé, un pare-feu ou un répartiteur de charge a coupé la connexion inactive, ou des données que l'autre partie n'attendait pas ont été envoyées.
Aucun espace tampon disponible dans le noyau pour l'opération réseau ; apparaît généralement avec beaucoup de trafic ou lorsque les files des sockets sont pleines.
Le socket est déjà connecté.
Le socket n'est pas connecté : on a tenté d'envoyer ou de recevoir avant de se connecter, ou la connexion est déjà fermée. Sur un montage FUSE, il apparaît comme « Transport endpoint is not connected » lorsque son processus est mort ; on le corrige en démontant avec fusermount -u.
Impossible d'envoyer après avoir fermé ce sens du socket avec shutdown.
Trop de références ; sous Linux, lorsqu'on passe trop de descripteurs imbriqués par un socket Unix.
Le délai d'attente de la connexion a expiré car la destination n'a pas répondu. Cela vient généralement d'un pare-feu qui abandonne silencieusement les paquets, d'un hôte éteint ou d'une route qui n'aboutit pas.
La destination a refusé la connexion : la machine répond, mais personne n'écoute sur ce port ou un pare-feu répond par un rejet. Vérifiez que le service est en cours d'exécution et écoute sur la bonne interface, pas seulement sur 127.0.0.1.
L'hôte de destination est hors service.
Aucune route vers l'hôte : il ne répond pas à ARP sur le réseau local, ou un routeur ou un pare-feu signale qu'il est inaccessible.
Une opération est déjà en cours sur le socket, comme un connect non bloquant qui n'est pas encore terminé.
L'opération est en cours : un connect non bloquant a commencé et se terminera plus tard. Ce n'est pas une erreur ; il faut attendre avec poll ou select.
L'identifiant de fichier est devenu obsolète : sur NFS, le fichier ou le répertoire a été supprimé ou remplacé sur le serveur. On le résout en rouvrant le chemin ou en remontant.
La structure a besoin d'être nettoyée : le système de fichiers a détecté une corruption (sur ext4 et XFS, avec l'alias EFSCORRUPTED). Démontez-le et lancez fsck ou xfs_repair.
Même valeur :EFSCORRUPTED
Ce n'est pas un fichier nommé XENIX. C'est un code hérité inutilisé.
Aucun sémaphore XENIX disponible. C'est un code hérité inutilisé.
C'est un fichier nommé XENIX. C'est un code hérité inutilisé.
Erreur d'E/S distante, par exemple d'un périphérique I2C ou d'un disque distant qui n'a pas répondu.
Le quota de disque de l'utilisateur ou du groupe a été dépassé.
Aucun support dans le périphérique, comme un lecteur sans disque ou un lecteur de cartes vide.
Le type de support n'est pas le bon.
L'opération a été annulée, par exemple une E/S asynchrone ou une attente io_uring.
La clé nécessaire n'est pas dans le keyring du noyau. Apparaît avec des systèmes de fichiers chiffrés, comme fscrypt ou eCryptfs, lorsque la clé n'a pas été chargée.
La clé a expiré. PAM et Kerberos l'utilisent aussi lorsque le mot de passe ou le ticket a expiré.
La clé a été révoquée.
Le service a rejeté la clé.
Le propriétaire d'un mutex robuste est mort sans le libérer. Le nouveau propriétaire doit rendre cohérent l'état protégé et appeler pthread_mutex_consistent.
L'état protégé par un mutex robuste ne peut pas être récupéré, car le propriétaire précédent est mort et personne ne l'a marqué comme cohérent.
L'opération est impossible car la radio Wi-Fi ou Bluetooth est bloquée par RF-kill. Vérifiez rfkill list, l'interrupteur physique ou la touche du mode avion.
La page mémoire présente une erreur matérielle et le noyau l'a marquée comme empoisonnée.
Le type de fichier n'est pas adapté à l'opération. Il existe depuis longtemps sous macOS et BSD ; sous Linux, il a été ajouté récemment.
Trop de processus. BSD le définit pour la limite de processus, bien qu'en pratique fork renvoie EAGAIN.
La structure RPC est incorrecte (Sun RPC, utilisé par NFS).
La version RPC ne correspond pas (Sun RPC, utilisé par NFS).
Le programme RPC n'est pas disponible sur le serveur.
La version du programme RPC ne correspond pas.
La procédure n'existe pas dans le programme RPC.
Erreur d'authentification, par exemple lors du montage d'un partage NFS.
Un authentificateur est nécessaire pour l'opération.
Le périphérique est éteint.
Erreur du périphérique, par exemple une imprimante sans papier.
L'exécutable n'est pas valide.
L'exécutable est destiné à un autre type de CPU, comme un binaire uniquement x86_64 sur un Mac Apple Silicon sans Rosetta 2, ou un binaire ARM sur un Mac Intel.
La version de la bibliothèque partagée ne correspond pas.
Le fichier Mach-O est mal formé ou endommagé.
L'attribut étendu n'existe pas ; il équivaut à ENODATA sous Linux. Apparaît avec xattr, par exemple lorsqu'on retire com.apple.quarantine d'un fichier qui ne l'a pas.
Aucune politique enregistrée sous ce nom dans le MAC Framework.
La file de sortie de l'interface réseau est pleine.
Les capacités sont insuffisantes : les appels restreints par un sandbox le renvoient.
Le terminal qui contrôlait le processus a été fermé ou la session SSH a été coupée. De nombreux démons, comme nginx, sshd ou rsyslog, l'utilisent comme une demande de relecture de la configuration ; nohup, tmux et screen évitent qu'il ferme les processus à la sortie.
Interruption depuis le clavier avec Ctrl+C. Le programme peut l'intercepter pour se terminer proprement. Code de sortie 130.
Sortie depuis le clavier avec Ctrl+\. Termine le processus avec un vidage mémoire ; la JVM, elle, l'utilise pour afficher l'état des threads.
Le processeur a rencontré une instruction illégale : un binaire compilé pour un CPU plus récent (par exemple, avec AVX2 ou AVX-512 sur un processeur qui ne les prend pas en charge), du code endommagé ou un saut vers des données.
Trappe de débogage : les débogueurs l'utilisent pour les points d'arrêt. S'il arrive sans débogueur, c'est généralement une erreur détectée par le programme lui-même, comme les vérifications de Swift sous macOS.
Le processus a appelé abort() : une assertion qui a échoué, une exception C++ non interceptée ou une corruption du tas détectée par la bibliothèque C (« double free or corruption »). Code de sortie 134.
Même valeur :SIGIOT
Erreur de bus : un accès mémoire mal aligné sur certaines architectures, ou un accès à une partie d'un fichier mappé avec mmap qui n'existe plus parce que le fichier a été tronqué. Se produit aussi lorsque /dev/shm est plein.
Exception arithmétique. Malgré son nom, la cause la plus courante est une division entière par zéro.
Termine le processus immédiatement : il ne peut être ni intercepté, ni bloqué, ni ignoré. Il est envoyé par kill -9, par l'OOM killer du noyau lorsque la mémoire est épuisée, et par Docker ou Kubernetes lorsqu'un conteneur dépasse sa limite de mémoire (OOMKilled) ou ne se termine pas à temps après SIGTERM. Code de sortie 137.
Signal libre que chaque application peut utiliser à sa guise ; par exemple, dd affiche sa progression et nginx rouvre ses logs.
Violation de segment (« Segmentation fault ») : un accès à une mémoire non valide, comme déréférencer un pointeur nul, sortir des limites d'un tableau ou faire déborder la pile avec une récursion infinie. Code de sortie 139.
Second signal libre que chaque application peut utiliser à sa guise.
Écriture dans un pipe ou un socket sans lecteur. C'est normal dans cmd | head, où le lecteur se termine avant ; les serveurs l'ignorent généralement et gèrent l'erreur EPIPE. Code de sortie 141.
Le temporisateur programmé avec alarm ou setitimer a expiré.
Demande d'arrêt propre. C'est le signal par défaut de kill, de systemctl stop, de docker stop et de Kubernetes lors de la suppression d'un pod ; le processus devrait fermer ses connexions et se terminer. Code de sortie 143.
Erreur de pile du coprocesseur. Inutilisé dans les Linux actuels.
Un processus enfant s'est terminé, a été suspendu ou a repris. Le parent doit le récupérer avec wait ; sinon, l'enfant reste à l'état de zombie.
Même valeur :SIGCLD
Reprend un processus suspendu, comme le font fg et bg dans le shell.
Suspend le processus ; il ne peut être ni intercepté ni ignoré. Le processus reprend avec SIGCONT.
Suspension depuis le terminal avec Ctrl+Z. Contrairement à SIGSTOP, le programme peut l'intercepter.
Un processus en arrière-plan a tenté de lire depuis le terminal.
Un processus en arrière-plan a tenté d'écrire sur le terminal alors que stty tostop est actif, ou d'en modifier la configuration.
Des données urgentes (hors bande) sont arrivées sur un socket. Go l'utilise en interne pour interrompre les goroutines.
La limite de temps CPU du processus a été dépassée (ulimit -t).
La taille maximale de fichier autorisée pour le processus a été dépassée (ulimit -f).
Le temporisateur virtuel, qui ne compte que le temps CPU du processus, a expiré.
Le temporisateur de profilage, utilisé par les profileurs, a expiré.
La taille de la fenêtre du terminal a changé ; les programmes en plein écran l'utilisent pour se redessiner.
Des E/S sont disponibles sur un descripteur configuré avec O_ASYNC. Sous Linux, SIGPOLL est le même signal.
Même valeur :SIGPOLL
Panne de courant, qu'un logiciel d'onduleur signale au système init.
Appel système incorrect. Aujourd'hui, la cause habituelle est un filtre seccomp qui le bloque, comme dans les conteneurs.
Trappe d'émulation (EMT). Existe sous macOS et BSD, mais pas sous Linux sur x86 ni sur ARM.
Demande d'information avec Ctrl+T dans le terminal de macOS et de BSD ; de nombreuses commandes répondent en affichant leur progression.
La commande s'est terminée correctement. C'est le seul code qui signifie la réussite : toute autre valeur indique une erreur.
Erreur générale ; chaque programme décide de sa signification. Le détail se trouve généralement dans ce que la commande a écrit sur stderr. grep et diff l'utilisent dans un autre sens : « aucune correspondance trouvée » ou « les fichiers sont différents ».
Mauvaise utilisation d'une commande interne du shell ou erreur de syntaxe dans le script. De nombreux programmes l'utilisent aussi pour des options non valides, et grep pour de vraies erreurs.
La commande a été mal utilisée : il manque des arguments, il y en a trop ou une option est incorrecte.
Les données d'entrée ont un format incorrect.
Un fichier d'entrée n'existe pas ou ne peut pas être lu.
L'utilisateur indiqué n'existe pas ; utilisé surtout par les programmes de messagerie.
Le nom d'hôte n'existe pas.
Un service nécessaire n'est pas disponible, ou une défaillance qui n'entre dans aucune autre catégorie s'est produite.
Erreur interne du programme.
Erreur du système d'exploitation, comme l'impossibilité de faire un fork ou de créer un pipe.
Un fichier système, comme /etc/passwd, est manquant ou contient une erreur.
Impossible de créer un fichier de sortie.
Erreur d'entrée/sortie lors de la lecture ou de l'écriture d'un fichier.
Échec temporaire : il vaut mieux réessayer plus tard. Les serveurs de messagerie l'utilisent pour laisser le message dans la file d'attente.
Le système distant a répondu quelque chose qui ne respecte pas le protocole.
Permissions insuffisantes pour l'opération.
Il y a une erreur dans la configuration.
La commande timeout l'a terminée parce qu'elle a dépassé le délai indiqué.
docker run lui-même a échoué avant d'exécuter le conteneur, par exemple à cause d'une option incorrecte ou d'une erreur du démon. GNU timeout le renvoie aussi lorsque c'est lui qui échoue.
Le fichier existe, mais ne peut pas être exécuté : il lui manque la permission d'exécution, c'est un répertoire ou c'est un binaire d'une autre architecture. Dans Docker, la commande du conteneur n'est pas exécutable.
Commande introuvable : elle n'est pas installée, n'est pas dans le PATH ou son nom est mal orthographié. Dans les scripts, il apparaît aussi lorsque l'interpréteur de la ligne #! manque ; dans Docker, lorsque la commande du conteneur n'existe pas dans l'image.
Les codes supérieurs à 128 indiquent qu'un signal a terminé le processus, mais 128 ne correspond à aucun. Git l'utilise pour toutes ses erreurs fatales (« fatal: … »), comme un dépôt qui n'existe pas ou un échec d'authentification lors d'un clonage.
Le code de sortie était hors limites : exit -1 arrive comme 255, car seuls 8 bits sont conservés. ssh le renvoie aussi lorsque la connexion ou l'authentification échoue, pour le distinguer du code de la commande distante.
Les valeurs Linux sont celles de x86, x86-64 et ARM ; Alpha, MIPS, SPARC et PA-RISC numérotent différemment certains errno et signaux. Les messages en anglais sont ceux qu'affichent strerror et strsignal dans la glibc, et dans macOS lorsqu'ils diffèrent. Les codes de sortie supérieurs à 128 sont interprétés comme 128 plus le numéro du signal, ce qui est la convention de bash, de Docker et de Kubernetes.
Comment ça marche
Lorsqu'un appel système échoue sous Linux, il renvoie -1 et place dans la variable errno un numéro qui indique pourquoi : 2 est ENOENT, le fichier n'existe pas ; 13 est EACCES, permission refusée. strerror convertit ce numéro en texte affiché à l'écran, comme « No such file or directory ». Python l'affiche sous la forme [Errno 13], Node.js sous la forme code: 'ECONNREFUSED' et Go, Rust ou Java avec le même texte. Les numéros de 1 à 34 viennent de l'Unix d'origine et sont identiques sur tous les systèmes ; les suivants ont été numérotés par chaque système à sa manière, si bien que ECONNREFUSED vaut 111 sous Linux et 61 sous macOS. Le nom est portable ; le numéro, non.
Les signaux sont des avis que le noyau ou un autre processus envoient à un processus : SIGINT quand on appuie sur Ctrl+C, SIGTERM pour lui demander de se terminer, SIGKILL pour le tuer sans lui demander son avis, SIGSEGV lorsqu'il accède à une mémoire non valide. Chacun a une action par défaut, et presque tous peuvent être interceptés pour faire autre chose. Lorsqu'un signal tue un processus, le shell l'indique par le code de sortie 128 plus le numéro du signal : 137 est SIGKILL (9), 139 est SIGSEGV (11) et 143 est SIGTERM (15). Docker et Kubernetes utilisent la même convention.
Le code de sortie est le numéro qu'un programme laisse en se terminant : 0 signifie la réussite et toute autre valeur, une erreur. Seuls 8 bits sont conservés, il va donc de 0 à 255. Il existe peu de conventions : 126 et 127 sont utilisés par le shell lorsqu'il ne peut pas exécuter la commande ou ne la trouve pas, ceux de 64 à 78 sont définis par sysexits.h de BSD, et le reste est décidé par chaque programme, comme grep, qui renvoie 1 lorsqu'il ne trouve rien.
Exemples
Last State: Terminated · Reason: OOMKilled · Exit Code: 137137 = 128 + 9 · SIGKILLLe conteneur a dépassé sa limite de mémoire et le noyau l'a tué avec SIGKILL. Il faut augmenter la limite dans resources.limits.memory ou chercher pourquoi le processus consomme autant ; le redémarrer ne résout rien.Error: connect ECONNREFUSED 127.0.0.1:5432ECONNREFUSED · Linux 111 · macOS 61 · Connection refusedNode.js n'a pas pu se connecter à PostgreSQL car personne n'écoute sur le port 5432. Si l'application tourne dans un conteneur, 127.0.0.1 est le conteneur lui-même et non la machine : il faut utiliser le nom du service de la base de données.OSError: [Errno 48] Address already in useEADDRINUSE · Linux 98 · macOS 48Le 48 trahit que le programme tourne sous macOS : sous Linux, la même erreur est la 98. Dans les deux cas, un autre processus utilise déjà le port ; lsof -i :PORT indique lequel.Cas d'usage
- Comprendre une erreur d'une application en Python, Node.js, Go ou C qui n'affiche que le numéro ou le nom de l'errno.
- Découvrir, à partir de son code de sortie, pourquoi un conteneur Docker s'est arrêté ou pourquoi un pod Kubernetes redémarre.
- Convertir un numéro d'errno macOS en son nom correct, qui à partir de 35 ne coïncide plus avec celui de Linux.
- Interpréter le code de sortie d'un script, d'un cron ou d'un job de CI qui a échoué.
- Choisir quel signal envoyer avec kill et savoir ce que fait le processus s'il ne l'intercepte pas.
- Écrire une gestion d'erreurs portable qui compare par nom plutôt que par numéro.
Questions fréquentes
Que signifie l'exit code 137 ?
Que le processus a été terminé par le signal 9, SIGKILL (128 + 9). La cause la plus courante est la mémoire : le conteneur a dépassé sa limite, et Kubernetes l'indique comme OOMKilled, ou l'OOM killer du noyau a choisi ce processus, ce qui apparaît dans dmesg sous la forme « Out of memory: Killed process ». Cela se produit aussi avec docker kill, ou lorsque le processus ne se termine pas dans le délai imparti après SIGTERM : 10 secondes avec docker stop et 30 avec Kubernetes.
Quelle est la différence entre SIGTERM et SIGKILL ?
SIGTERM demande au processus de se terminer, et le processus peut l'intercepter pour fermer ses connexions, enregistrer ses données et sortir. Avec SIGKILL, le noyau le termine sur-le-champ, sans que le processus puisse rien faire. La bonne pratique consiste à envoyer SIGTERM, attendre quelques secondes et ne recourir à SIGKILL que s'il est toujours en vie, ce que font systemd, docker stop et Kubernetes.
Pourquoi le même errno a-t-il un autre numéro sous macOS ?
Parce que POSIX définit les noms mais pas les numéros. De 1 à 34, tous les systèmes ont hérité de ceux de l'Unix d'origine ; ensuite, BSD, dont descend macOS, et System V, qu'a suivi Linux, les ont numérotés séparément. C'est pourquoi il vaut mieux toujours comparer par nom, avec errno.ECONNREFUSED en Python, err.code en Node.js ou la constante en C, et non par numéro.
Quelle est la différence entre EACCES et EPERM ?
EACCES (« Permission denied ») signifie que les permissions du fichier ou d'un répertoire du chemin ne le permettent pas, ou qu'une ACL ou SELinux l'empêche : cela se résout avec chmod, chown ou la politique correspondante. EPERM (« Operation not permitted ») signifie que l'opération elle-même exige des privilèges, quelles que soient les permissions, comme changer le propriétaire d'un fichier ou tuer un processus d'un autre utilisateur : il faut être root, disposer d'une capability ou retirer un attribut comme celui d'immuabilité.
Comment voir le code de sortie d'une commande ou d'un conteneur ?
Dans bash et zsh, echo $? affiche celui de la dernière commande ; dans PowerShell, $LASTEXITCODE. Dans Docker, docker ps -a l'affiche dans la colonne STATUS, comme « Exited (137) ». Dans Kubernetes, kubectl describe pod l'affiche dans « Last State: Terminated », avec le motif, comme OOMKilled ou Error.