Existe-t-il des codes d'état de sortie standard sous Linux?

308

Un processus est considéré comme terminé correctement sous Linux si son état de sortie était 0.

J'ai vu que les erreurs de segmentation entraînent souvent un état de sortie de 11, bien que je ne sais pas si c'est simplement la convention où je travaille (les applications qui ont échoué comme ça ont toutes été internes) ou une norme.

Existe-t-il des codes de sortie standard pour les processus sous Linux?

Nathan Fellman
la source
6
si vous cherchez la chose appelée "numéro d'erreur système" renvoyée par les fonctions système, regardez ici errno
marinara

Réponses:

86

8 bits du code retour et 8 bits du numéro du signal de suppression sont mélangés en une seule valeur 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? Traditionnellement, le shell stocke uniquement un code retour 8 bits, mais définit le bit haut si le processus s'est terminé anormalement.

$ sh -c 'exit 42'; écho $?
42
$ sh -c 'kill -SEGV $$'; écho $?
Erreur de segmentation
139
$ expr 139 - 128
11

Si vous voyez autre chose que cela, alors le programme a probablement un SIGSEGVgestionnaire de signal qui appelle ensuite exitnormalement, donc il n'est pas réellement tué par le signal. (Les programmes peuvent choisir de gérer tous les signaux en dehors de SIGKILLet SIGSTOP.)

éphémère
la source
8
Étant donné la façon dont la question apparaît maintenant, cela ne semble pas être la réponse la plus utile (et donc acceptée).
David J.
332

Partie 1: Guide de script Bash avancé

Comme toujours, le Guide de script avancé Bash contient d' excellentes informations : (Cela a été lié dans une autre réponse, mais à une URL non canonique.)

1: Catchall pour les erreurs générales
2: Mauvaise utilisation des commandes internes du shell (selon la documentation de Bash)
126: La commande invoquée ne peut pas s'exécuter
127: "commande introuvable"
128: Argument invalide pour quitter
128 + n: Signal d'erreur fatal "n"
255: Quitter état hors plage (la sortie ne prend que des arguments entiers compris entre 0 et 255)

Partie 2: sysexits.h

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 */
Schof
la source
5
Notez que dans certaines versions d'Unix, certaines commandes utilisent un état de sortie de 2 pour indiquer d'autres choses. Par exemple, de nombreuses implémentations de grep utilisent un état de sortie de 2 pour indiquer une erreur et utilisent un état de sortie de 1 pour signifier qu'aucune ligne sélectionnée n'a été trouvée.
NamshubWriter
3
Sur les BSD, il y a une page de manuel résumant les informations de sysexits.h:man sysexits
georgebrock
6
Ce que @NamshubWriter a dit. Le statut de sortie 2 est le go-to universel pour une utilisation incorrecte de la ligne de commande dans les utilitaires Unix, pas seulement dans "certaines versions d'Unix" mais en général. L'en-tête affiché dans cette réponse ne reflète pas les conventions réelles, maintenant ou quand il a été écrit en 1987.
alexis
L'ABS n'est pas "génial". Veuillez lire sur le sujet; il n'est pas exactement difficile de trouver des critiques.
tripleee
Mais où est le véritable code source officiel sysexits.h? La page de manuel à laquelle tout le monde fait référence n'est que de la prose. Par exemple, il fait référence EX_OKmais ne le définit pas de manière normative comme les autres codes. Y en a-t-il d'autres qui manquent?
Garret Wilson
71

'1' >>> Catchall pour les erreurs générales

'2' >>> Mauvais usage des commandes internes de shell (selon la documentation de Bash)

'126' >>> La commande invoquée ne peut pas s'exécuter

'127' >>> "commande introuvable"

'128' >>> Argument invalide pour quitter

'128 + n' >>> Signal d'erreur fatale "n"

'130' >>> Script terminé par Control-C

'255' >>> Etat de sortie hors plage

C'est pour bash. Cependant, pour d'autres applications, il existe différents codes de sortie.

segfault
la source
1
On dirait que vous avez tous les deux répondu dans la même minute. Tian devrait être assez rapide pour voir vos liens et les coller.
Nathan Fellman
6
Notez que «contrôle-C donne 130» est cohérent avec «128 + n» pour le signal n; control-C génère SIGINT qui est le signal 2.
Jonathan Leffler
3
Cela semble être plagié de l'ABS sans attribution. (Nous pouvons le dire parce que l'ABS contient des informations incorrectes ou au moins trompeuses.)
tripleee
4
Ce sont des codes de sortie RÉSERVÉS, selon le Guide avancé de Bash-Scripting . Cela signifie que ces valeurs doivent donc être évitées pour les paramètres de sortie spécifiés par l'utilisateur .
ingyhere
53

Aucune des réponses plus anciennes ne décrit correctement l'état de sortie 2. Contrairement à ce qu'ils prétendent, le statut 2 correspond à ce que vos utilitaires de ligne de commande retournent réellement lorsqu'ils sont appelés de manière incorrecte. (Oui, une réponse peut avoir neuf ans, avoir des centaines de votes positifs et toujours avoir tort.)

Voici la convention de statut de sortie réelle et de longue date pour la terminaison normale, c'est-à-dire pas par signal:

  • Statut de sortie 0: succès
  • Etat de sortie 1: "échec", tel que défini par le programme
  • Etat de sortie 2: erreur d'utilisation de la ligne de commande

Par exemple, diffrenvoie 0 si les fichiers qu'il compare sont identiques et 1 s'ils diffèrent. Par convention de longue date, les programmes unix retournent état de sortie 2 lorsqu'il est appelé de manière incorrecte ( les options inconnues, mauvais nombre d'arguments, etc.) Par exemple, diff -N, grep -You diff a b cgenerera à $?être mis à 2. Ceci est et a été la pratique depuis la premiers jours d'Unix dans les années 1970.

La réponse acceptée explique ce qui se passe lorsqu'une commande se termine par un signal. En bref, la résiliation en raison d'un signal non capturé entraîne un état de sortie 128+[<signal number>. Par exemple, la terminaison par SIGINT( signal 2 ) entraîne l'état de sortie 130.

Remarques

  1. Plusieurs réponses définissent le statut de sortie 2 comme "Mauvaise utilisation des commandes bash". Cela s'applique uniquement lorsque bash (ou un script bash) se termine avec le statut 2. Considérez-le comme un cas particulier d'erreur d'utilisation incorrecte.

  2. Dans sysexits.h, mentionné dans la réponse la plus populaire , l'état de sortie EX_USAGE("erreur d'utilisation de la ligne de commande") est défini comme étant 64. Mais cela ne reflète pas la réalité: je ne connais aucun utilitaire Unix commun qui renvoie 64 en cas d'appel incorrect (exemples bienvenus ). Une lecture attentive du code source révèle que sysexits.hc'est de l'aspiration, plutôt qu'un reflet de la véritable utilisation:

     *    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 oth­er 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 elle. Plus c'est dommage.

alexis
la source
Que doit faire un retour du programme quand il fait poignée fin en attrapant SIGINT / Ctrl-C? Toujours 130? Est-ce que l'utilisation d'un autre shell en plus de bash est importante?
Gringo Suave
1
Le shell qui exécute le programme n'est pas pertinent; un processus pourrait théoriquement choisir de quitter avec un statut différent en fonction de son processus parent, mais je n'ai jamais, jamais entendu parler d'un cas où cela se produit.
alexis
1
Si un programme intercepte SIGINT, nettoie et quitte de toute façon, l'état est celui qui a du sens pour le programme. Par exemple, moreréinitialise les modes du terminal et quitte avec le statut 0 (vous pouvez l'essayer).
alexis
1
Cette réponse implique un degré de normalisation beaucoup plus élevé que ce qui est réellement le cas. Il n'y a pas de normalisation appropriée de la signification de la valeur 2, et la pratique réelle est alors, de façon prévisible, très mitigée. Il est vrai que de nombreux outils renvoient 2 pour une mauvaise utilisation mais ce n'est pas exactement bien défini ce que signifie une «mauvaise utilisation», et beaucoup d'autres n'adhèrent pas à cette convention.
tripleee
@tripleee "tools" n'est pas bien défini non plus! :-) Bien sûr, tout le monde peut écrire un programme en ligne de commande et il peut tout retourner, mais les "utilitaires de ligne de commande" Unix qui existent depuis plus longtemps que Linux, ou le contenu de GNU coreutils, sont assez cohérente à ce sujet. Si vous pensez le contraire, veuillez nommer certains outils de ce groupe qui n'utilisent pas le statut 2 de cette façon. De plus, «mauvaise utilisation» est votre terme (et je suis d'accord que c'est un terme vague); J'ai écrit "erreur d'utilisation de la ligne de commande", qui est assez spécifique: options inexistantes ou incompatibles, mauvais nombre d'arguments non-option, etc.
alexis
25

Il n'y a pas de code de sortie standard, à part 0 signifiant succès. Non nul n'est pas nécessairement synonyme d'échec non plus.

stdlib.h définit EXIT_FAILUREcomme 1 et EXIT_SUCCESScomme 0, mais c'est à peu près tout.

Le 11 sur segfault est intéressant, 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, que ce soit dans le noyau ou dans le shell, qui traduit cela en code de sortie.

Chris Arguin
la source
20

sysexits.h a une liste de codes de sortie standard. Cela semble remonter au moins à 1993 et ​​certains grands projets comme Postfix l'utilisent, donc j'imagine que c'est la voie à suivre.

Depuis la page de manuel d'OpenBSD:

Selon le style (9), il n'est pas recommandé d'appeler exit (3) avec des valeurs arbitraires pour indiquer une condition d'échec à la fin d'un programme. Au lieu de cela, les codes de sortie prédéfinis des sysexits doivent être utilisés, afin que l'appelant du processus puisse obtenir une estimation approximative de la classe de défaillance sans rechercher le code source.

la source
8

Dans une première approximation, 0 est un succès, non nul est un échec, 1 étant un échec général et tout ce qui est supérieur à un étant un échec spécifique. Mis à part les exceptions triviales de faux et de test, qui sont toutes deux conçues pour donner 1 pour succès, il y a quelques autres exceptions que j'ai trouvées.

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 réussir, mais peut-être aussi.

La commande diff donne 0 si les fichiers comparés sont identiques, 1 s'ils diffèrent et 2 si les binaires sont différents. 2 signifie également l'échec. La commande less donne 1 pour échec, sauf si vous ne fournissez pas d'argument, auquel cas, elle quitte 0 malgré l'échec.

La commande more et la commande spell donnent 1 pour é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 ces cas, ils quittent 0 malgré l'échec.

Ensuite, la commande expr donne 1 pour succès sauf si la sortie est la chaîne vide ou zéro, auquel cas, 0 est réussi. 2 et 3 sont un échec.

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 quitte 1, mais il quitte 2 pour un véritable échec (comme une autorisation refusée). Klist quitte également 1 lorsqu'il ne parvient pas à trouver un ticket, bien que ce ne soit pas plus un échec que lorsque grep ne trouve pas de modèle, ou lorsque vous ls un répertoire vide.

Donc, malheureusement, les pouvoirs Unix ne semblent imposer aucun ensemble logique de règles, même sur les exécutables très couramment utilisés.

Frédéric
la source
J'étais sur le point de souligner le comportement de diff aussi. wget a également des erreurs détaillées (par exemple 6 pour l'échec de l'authentification), mais alors elles utilisent 1 = erreur générique, 2..n = erreur spécifique
PypeBros
5

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 affecté à la variable d'état $? est alors à la coquille. Bash conserve les 7 bits inférieurs de l'état, puis utilise 128 + (signal nr) pour indiquer un signal.

La seule convention "standard" pour les programmes est 0 pour le succès, non nulle pour l'erreur. Une autre convention utilisée est de retourner errno en cas d'erreur.

Dean Povey
la source
3

Les codes de sortie Unix standard sont définis par sysexits.h, comme l'a mentionné une autre affiche. 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 retour. Ce signal est généré par le noyau en réponse à un mauvais accès à la page, ce qui provoque l'arrêt du programme. Une liste de signaux peut être trouvée dans la page de manuel des signaux (exécutez "man signal").

Daniel Schuler
la source
1

Lorsque Linux renvoie 0, cela signifie le 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 ...!

À propos du code d'erreur 11, il s'agit en effet du numéro de défaut de segmentation, ce qui signifie principalement que le programme a accédé à un emplacement mémoire qui n'a pas été attribué.

Amadeus45
la source
1
C'est toujours 11 parce que le noyau le tue et attribue la "valeur de sortie". De même, les autres types de défauts obtiendront toujours la même valeur de sortie.
Alex Gartrell