Un processus est considéré comme s’être achevé correctement sous Linux si son état de sortie était 0.
J'ai constaté que les erreurs de segmentation entraînent souvent un statut de sortie égal à 11, bien que je ne sache pas s'il s'agit simplement de la convention dans laquelle je travaille (les applications qui ont échoué de la sorte ont toutes été internes) ou d'une norme.
Existe-t-il des codes de sortie standard pour les processus sous Linux?
8 bits du code de retour et 8 bits du numéro du signal de destruction sont mélangés dans une valeur unique au retour de wait(2)
& co. .
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
int main() {
int status;
pid_t child = fork();
if (child <= 0)
exit(42);
waitpid(child, &status, 0);
if (WIFEXITED(status))
printf("first child exited with %u\n", WEXITSTATUS(status));
/* prints: "first child exited with 42" */
child = fork();
if (child <= 0)
kill(getpid(), SIGSEGV);
waitpid(child, &status, 0);
if (WIFSIGNALED(status))
printf("second child died with %u\n", WTERMSIG(status));
/* prints: "second child died with 11" */
}
Comment déterminez-vous le statut de sortie? En règle générale, le shell ne stocke qu'un code de retour de 8 bits, mais définit le bit haut si le processus s'est terminé de manière anormale.
$ sh -c 'sortie 42'; echo $? 42 $ sh -c 'kill -SEGV $$'; echo $? Erreur de segmentation 139 $ expr 139 - 128 11
Si vous voyez autre chose que cela, alors le programme a probablement un gestionnaire de signal SIGSEGV
qui appelle ensuite exit
normalement, afin qu'il ne soit pas réellement tué par le signal. (Les programmes peuvent choisir de gérer tous les signaux autres que SIGKILL
et SIGSTOP
.)
Comme toujours, le Guide de script avancé de Bash a ne bonne information : (Ceci était lié à une autre réponse, mais à une URL non canonique.)
1: Attrape-tout pour les erreurs générales
2: Utilisation abusive des commandes internes de Shell (d'après la documentation de Bash)
126: La commande appelée ne peut pas être exécutée
127: "commande non trouvée"
128: Argument non valide pour sortir
128 + n: Signal d'erreur fatal "n"
255: Statut de sortie hors limites (exit prend uniquement des arguments entiers compris entre 0 et 255)
Les références ABSG sysexits.h
.
Sous Linux:
$ find /usr -name sysexits.h
/usr/include/sysexits.h
$ cat /usr/include/sysexits.h
/*
* Copyright (c) 1987, 1993
* The Regents of the University of California. All rights reserved.
(A whole bunch of text left out.)
#define EX_OK 0 /* successful termination */
#define EX__BASE 64 /* base value for error messages */
#define EX_USAGE 64 /* command line usage error */
#define EX_DATAERR 65 /* data format error */
#define EX_NOINPUT 66 /* cannot open input */
#define EX_NOUSER 67 /* addressee unknown */
#define EX_NOHOST 68 /* Host name unknown */
#define EX_UNAVAILABLE 69 /* service unavailable */
#define EX_SOFTWARE 70 /* internal software error */
#define EX_OSERR 71 /* system error (e.g., can't fork) */
#define EX_OSFILE 72 /* critical OS file missing */
#define EX_CANTCREAT 73 /* can't create (user) output file */
#define EX_IOERR 74 /* input/output error */
#define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */
#define EX_PROTOCOL 76 /* remote error in protocol */
#define EX_NOPERM 77 /* permission denied */
#define EX_CONFIG 78 /* configuration error */
#define EX__MAX 78 /* maximum listed value */
'1' >>> Récupération pour erreurs générales
'2' >>> Mauvaise utilisation des fonctions intégrées de Shell (d'après la documentation de Bash)
'126' >>> La commande appelée ne peut pas être exécutée
'127' >>> "commande introuvable"
'128' >>> Argument non valide pour sortir
'128 + n' >>> Signal d'erreur fatal "n"
'130' >>> Script terminé par Control-C
'255' >>> Statut de sortie hors limites
Ceci est pour bash. Cependant, pour d'autres applications, il existe différents codes de sortie.
Aucune des réponses les plus anciennes ne décrit correctement le statut de sortie 2. Contrairement à ce qu'ils prétendent, le statut 2 correspond à ce que vos utilitaires de ligne de commande renvoient en cas d'appel incorrect. (Oui, une réponse peut avoir neuf ans, des centaines de votes positifs, et encore avoir tort.)
Voici la convention de statut de sortie réelle et ancienne pour une terminaison normale, c'est-à-dire non par signal:
Par exemple, diff
renvoie 0 si les fichiers qu'il compare sont identiques et 1 s'ils diffèrent. Selon une convention ancienne, les programmes Unix retournent le statut de sortie 2 lorsqu'ils sont appelés de manière incorrecte (options inconnues, nombre d'arguments erroné, etc.) . Par exemple, _diff -N
_, _grep -Y
_ ou _diff a b c
_ aura pour résultat que _$?
_ sera défini sur 2. C’est et est la pratique depuis les débuts d’Unix dans les années 1970.
Le réponse acceptée explique ce qui se produit lorsqu'une commande est terminée par un signal. En bref, une terminaison due à un signal non capturé résulte en état de sortie _128+[<signal number>
_. Par exemple, la terminaison par SIGINT
( signal 2 ) entraîne le statut de sortie 130.
Plusieurs réponses définissent le statut de sortie 2 comme "Mauvaise utilisation des commandes intégrées bash". Ceci ne s'applique que lorsque bash (ou un script bash) se ferme avec le statut 2. Considérez-le comme un cas particulier d'erreur d'utilisation incorrecte.
Dans sysexits.h
, mentionné dans le réponse la plus populaire , l'état de sortie _EX_USAGE
_ ("erreur d'utilisation de la ligne de commande") est défini sur 64. Mais cela ne reflète pas la réalité: je ne suis pas au courant de aucun utilitaire Unix commun qui renvoie 64 en cas d’appel incorrect (exemples bienvenus). Une lecture attentive de code source révèle que _sysexits.h
_ est une aspiration plutôt qu'un reflet d'un véritable usage:
_* This include file attempts to categorize possible error * exit statuses for system programs, notably delivermail * and the Berkeley network. * Error numbers begin at EX__BASE [64] to reduce the possibility of * clashing with other exit statuses that random programs may * already return.
_
En d'autres termes, ces définitions ne reflètent pas la pratique courante à l'époque (1993) mais étaient intentionnellement incompatibles avec celle-ci. Plus est la pitié.
Il n'y a pas de codes de sortie standard, mis à part 0, ce qui correspond au succès. Non nul ne signifie pas nécessairement échec non plus.
stdlib.h définit EXIT_FAILURE
comme 1 et EXIT_SUCCESS
comme 0, mais c'est à peu près tout.
La valeur 11 sur segfault est intéressante, car 11 est le numéro de signal que le noyau utilise pour tuer le processus en cas de segfault. Il existe probablement un mécanisme, dans le noyau ou dans le shell, qui le traduit en code de sortie.
sysexits.h a une liste de codes de sortie standard. Il semble que cela remonte à au moins 1993 et que de gros projets comme Postfix l'utilisent, alors j'imagine que c'est la voie à suivre.
Depuis la page de manuel OpenBSD:
Selon le style (9), il n'est pas recommandé d'appeler exit (3) avec des valeurs arbitraires pour indiquer une défaillance lors de la fin d'un programme. Au lieu de cela, les codes de sortie prédéfinis de sysexits doivent être utilisés, afin que l'appelant du processus puisse obtenir une estimation approximative de la classe de défaillance sans consulter le code source.
En première approximation, 0 est le succès, non nul est un échec, 1 étant un échec général et tout plus grand qu'un étant un échec spécifique. Mis à part les exceptions triviales de false et de test, qui sont toutes deux conçues pour donner 1 pour succès, il existe quelques autres exceptions que j'ai trouvées.
De manière plus réaliste, 0 signifie succès ou peut-être échec, 1 signifie échec général ou peut-être succès, 2 signifie échec général si 1 et 0 sont tous deux utilisés pour le succès, mais peut-être aussi le succès.
La commande diff donne 0 si les fichiers comparés sont identiques, 1 s'ils diffèrent et 2 si les fichiers binaires sont différents. 2 signifie aussi échec. La commande less donne 1 en cas d'échec sauf si vous ne parvenez pas à fournir un argument. Dans ce cas, elle quitte 0 en dépit de l'échec.
La commande more et la commande spell donnent 1 en cas d'échec, sauf si l'échec est le résultat d'une autorisation refusée, d'un fichier inexistant ou d'une tentative de lecture d'un répertoire. Dans tous les cas, ils quittent 0 malgré l'échec.
Ensuite, la commande expr donne 1 en cas de succès sauf si la sortie est une chaîne vide ou zéro, auquel cas 0 est un succès. 2 et 3 sont des échecs.
Ensuite, il y a des cas où le succès ou l'échec est ambigu. Lorsque grep ne parvient pas à trouver un modèle, il se termine par 1, mais il en existe 2 pour un véritable échec (comme une autorisation refusée). Klist se ferme également 1 lorsqu'il ne parvient pas à trouver un ticket, bien que cela ne soit pas plus un échec que lorsque grep ne trouve pas de modèle ou que vous avez un répertoire vide.
Donc, malheureusement, les puissances Unix existantes ne semblent pas appliquer de règles logiques, même sur les exécutables les plus couramment utilisés.
Les programmes renvoient un code de sortie 16 bits. Si le programme a été tué avec un signal, l'octet de poids fort contient le signal utilisé, sinon l'octet de poids faible est l'état de sortie renvoyé par le programmeur.
Comment ce code de sortie est-il affecté à la variable d'état $? est alors à la coquille. Bash conserve les 7 bits inférieurs de l'état et utilise ensuite 128 + (signal nr) pour indiquer un signal.
La seule convention "standard" pour les programmes est 0 en cas de succès et non nulle en cas d'erreur. Une autre convention utilisée est de retourner errno en cas d'erreur.
Les codes de sortie Unix standard sont définis par sysexits.h, comme une autre affiche mentionnée. Les mêmes codes de sortie sont utilisés par les bibliothèques portables telles que Poco - en voici une liste:
http://pocoproject.org/docs/Poco.Util.Application.html#16218
Un signal 11 est un signal SIGSEGV (violation de segment) différent d'un code de retour. Ce signal est généré par le noyau en réponse à un mauvais accès de page, ce qui provoque la fermeture du programme. Vous trouverez une liste de signaux dans la page de manuel Signal (exécutez "man signal").
Lorsque Linux renvoie 0, cela signifie succès. Tout le reste signifie un échec, chaque programme a ses propres codes de sortie, il aurait donc été assez long de tous les lister ...!
En ce qui concerne le code d’erreur 11, il s’agit bien du numéro d’erreur de segmentation, ce qui signifie principalement que le programme a accédé à un emplacement de mémoire qui n’a pas été attribué.