Esistono codici di stato di uscita standard in Linux?


308

Un processo è considerato completato correttamente in Linux se il suo stato di uscita era 0.

Ho visto che gli errori di segmentazione spesso portano a uno stato di uscita di 11, anche se non so se questa è semplicemente la convenzione in cui lavoro (le app che hanno fallito in quel modo sono state tutte interne) o uno standard.

Esistono codici di uscita standard per i processi in Linux?


6
se stai cercando la cosa chiamata "numero errore di sistema" restituito dalle funzioni di sistema, guarda qui a errno
marinara,

Risposte:


86

8 bit del codice di ritorno e 8 bit del numero del segnale di uccisione vengono miscelati in un singolo valore al ritorno da 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" */
}

Come si determina lo stato di uscita? Tradizionalmente, la shell memorizza solo un codice di ritorno a 8 bit, ma imposta il bit alto se il processo è stato terminato in modo anomalo.

$ sh -c 'exit 42'; echo $?
42
$ sh -c 'kill -SEGV $$'; echo $?
Errore di segmentazione
139
$ espresso 139-128
11

Se stai vedendo qualcosa di diverso da questo, allora il programma probabilmente ha un SIGSEGVgestore di segnale che poi chiama exitnormalmente, quindi non viene effettivamente ucciso dal segnale. (I programmi possono scegliere di gestire qualsiasi segnale oltre a SIGKILLe SIGSTOP.)


8
Dato il modo in cui ora appare la domanda, questa non sembra essere la risposta più utile (e quindi accettata).
David J.

332

Parte 1: Guida avanzata agli script di Bash

Come sempre, la Guida allo scripting di Advanced Bash ha grandi informazioni : (Questo era collegato in un'altra risposta, ma a un URL non canonico.)

1: Catchall per errori generali
2: Uso improprio dei builtin della shell (secondo la documentazione di Bash)
126: Il comando invocato non può eseguire
127: "comando non trovato"
128: argomento non valido per uscire
128 + n: segnale di errore fatale "n"
255: Exit stato fuori intervallo (exit accetta solo argomenti interi nell'intervallo 0 - 255)

Parte 2: sysexits.h

I riferimenti ABSG sysexits.h.

Su 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 */

5
Si noti che in alcuni tipi di unix, alcuni comandi utilizzano uno stato di uscita di 2 per indicare altre cose. Ad esempio, molte implementazioni di grep usano uno stato di uscita di 2 per indicare un errore e usano uno stato di uscita di 1 per indicare che non sono state trovate linee selezionate.
NamshubWriter,

3
Su BSD c'è una pagina man che riassume le informazioni da sysexits.h:man sysexits
georgebrock

6
Cosa ha detto @NamshubWriter. Lo stato di uscita 2 è la soluzione universale per un utilizzo errato della riga di comando nelle utility Unix, non solo in "alcuni tipi di unix", ma in generale. L'intestazione mostrata in questa risposta non riflette le convenzioni attuali, ora o quando è stata scritta nel 1987.
alexis

L'ABS non è "eccezionale". Si prega di leggere sull'argomento; non è esattamente difficile trovare critiche.
tripla il

Ma dove si trova l'attuale codice sorgente ufficiale sysexits.h? La pagina man che tutti continuano a fare riferimento è solo in prosa. Ad esempio fa riferimento EX_OKma in realtà non lo definisce in modo normativo come gli altri codici. Ce ne sono altri che mancano?
Garret Wilson,

71

'1' >>> Catchall per errori generali

'2' >>> Uso improprio dei builtin della shell (secondo la documentazione di Bash)

'126' >>> Il comando invocato non può essere eseguito

'127' >>> "comando non trovato"

'128' >>> Argomento non valido per uscire

'128 + n' >>> Segnale di errore irreversibile "n"

'130' >>> Script terminato da Control-C

'255' >>> Esci dallo stato fuori intervallo

Questo è per bash. Tuttavia, per altre applicazioni, esistono diversi codici di uscita.


1
Sembra che entrambi abbiate risposto nello stesso minuto. Tian dovrebbe essere abbastanza veloce per vedere i tuoi link e incollarli.
Nathan Fellman,

6
Si noti che "control-C produce 130" è coerente con "128 + n" per il segnale n; control-C genera SIGINT che è il segnale 2.
Jonathan Leffler

3
Questo sembra essere plagiato dall'ABS senza attribuzione. (Possiamo dire perché l'ABS contiene informazioni errate o almeno fuorvianti.)
tripleee

4
Questi sono codici di uscita RISERVATI, secondo la Guida avanzata di script Bash . Ciò significa che questi valori dovrebbero quindi essere evitati per i parametri di uscita specificati dall'utente .
inghehere

53

Nessuna delle risposte precedenti descrive correttamente lo stato di uscita 2. Contrariamente a quanto sostengono, lo stato 2 è ciò che effettivamente restituiscono le utility della riga di comando quando vengono chiamate in modo errato. (Sì, una risposta può avere nove anni, avere centinaia di voti, ed essere ancora sbagliata.)

Ecco la convenzione di stato di uscita reale e di vecchia data per la terminazione normale, ovvero non per segnale:

  • Stato uscita 0: successo
  • Stato uscita 1: "errore", come definito dal programma
  • Stato uscita 2: errore di utilizzo della riga di comando

Ad esempio, diffrestituisce 0 se i file che confronta sono identici e 1 se differiscono. Per convenzione di vecchia data, i programmi unix restituiscono lo stato di uscita 2 se chiamati in modo errato (opzioni sconosciute, numero errato di argomenti, ecc.) Ad esempio diff -N, grep -Yo diff a b crisulteranno tutti $?impostati su 2. Questa è ed è stata la pratica dal primi giorni di Unix negli anni '70.

La risposta accettata spiega cosa succede quando un comando viene interrotto da un segnale. In breve, la terminazione dovuta a un segnale non rilevato provoca lo stato di uscita 128+[<signal number>. Ad esempio, la terminazione per SIGINT( segnale 2 ) porta allo stato di uscita 130.

Appunti

  1. Diverse risposte definiscono lo stato di uscita 2 come "Uso improprio di builtin bash". Questo si applica solo quando bash (o uno script bash) esce con lo stato 2. Consideralo un caso speciale di errore d'uso errato.

  2. In sysexits.h, menzionato nella risposta più popolare , lo stato di uscita EX_USAGE("errore di utilizzo della riga di comando") è definito come 64. Ma questo non riflette la realtà: non sono a conoscenza di alcuna utilità Unix comune che restituisce 64 in caso di invocazione errata (esempi benvenuti ). Un'attenta lettura del codice sorgente rivela che sysexits.hè un'aspirazione, piuttosto che un riflesso del vero utilizzo:

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

    In altre parole, queste definizioni non riflettono la pratica comune all'epoca (1993) ma erano intenzionalmente incompatibili con essa. Più è un peccato.


Cosa deve fare un ritorno programma quando si fa terminazione maniglia con la cattura di SIGINT / Ctrl-C? Ancora 130? L'uso di un'altra shell oltre a bash è importante?
Gringo Suave,

1
La shell che sta eseguendo il programma è irrilevante; un processo potrebbe teoricamente scegliere di uscire con uno stato diverso a seconda del processo principale, ma non ho mai, mai sentito parlare di un caso in cui ciò accade.
alexis,

1
Se un programma rileva SIGINT, pulisce ed esce comunque, lo stato è quello che ha senso per il programma. Ad esempio, moreripristinerà le modalità del terminale e uscirà con lo stato 0 (puoi provarlo).
alexis,

1
Questa risposta implica un livello di standardizzazione molto più elevato di quello che è effettivamente il caso. Non esiste un'adeguata standardizzazione del significato del valore 2 e la pratica effettiva è quindi prevedibilmente molto mista. È vero che molti strumenti restituiscono 2 per uso improprio, ma non è esattamente ben definito cosa significhi "uso improprio" e molti altri non aderiscono a questa convenzione.
triplo il

Anche gli "strumenti" di @tripleee non sono ben definiti! :-) Certo, chiunque può scrivere un programma da riga di comando e può restituire qualsiasi cosa, ma le "utility da riga di comando Unix" della vecchia scuola che sono in circolazione da più tempo di Linux, o il contenuto dei coreutils GNU, sono piuttosto coerente su questo. Se la pensi diversamente, dai un nome ad alcuni strumenti di questo gruppo che non usano lo stato 2 in questo modo. Inoltre, "uso improprio" è il tuo termine (e sono d'accordo che sia un termine vago); Ho scritto "errore di utilizzo della riga di comando", che è piuttosto specifico: opzioni inesistenti o incompatibili, numero errato di argomenti non opzionali, ecc.
alexis,

25

Non ci sono codici di uscita standard, a parte 0 che significa successo. Anche se diverso da zero non significa necessariamente fallimento.

stdlib.h definisce EXIT_FAILUREcome 1 e EXIT_SUCCESScome 0, ma questo è tutto.

L'11 su segfault è interessante, poiché 11 è il numero di segnale che il kernel usa per terminare il processo in caso di segfault. Probabilmente esiste un meccanismo, nel kernel o nella shell, che lo traduce nel codice di uscita.


20

sysexits.h ha un elenco di codici di uscita standard. Sembra risalire almeno al 1993 e alcuni grandi progetti come Postfix lo usano, quindi immagino che sia la strada da percorrere.

Dalla pagina man di OpenBSD:

Secondo lo stile (9), non è buona norma chiamare exit (3) con valori arbitrari per indicare una condizione di errore al termine di un programma. Al contrario, dovrebbero essere utilizzati i codici di uscita predefiniti di sysexits, in modo che il chiamante del processo possa ottenere una stima approssimativa della classe di errore senza cercare il codice sorgente.

8

Ad una prima approssimazione, 0 è successo, diverso da zero è fallimento, con 1 è un errore generale e qualcosa di più grande di uno è un errore specifico. A parte le banali eccezioni di falso e test, che sono entrambe progettate per dare 1 per il successo, ci sono alcune altre eccezioni che ho trovato.

Più realisticamente, 0 significa successo o forse fallimento, 1 significa fallimento generale o forse successo, 2 significa fallimento generale se 1 e 0 sono entrambi usati per il successo, ma forse anche successo.

Il comando diff dà 0 se i file confrontati sono identici, 1 se differiscono e 2 se i binari sono diversi. 2 significa anche fallimento. Il comando less fornisce 1 per errore a meno che non si riesca a fornire un argomento, nel qual caso, esce 0 nonostante non sia riuscito.

Il comando maggiore e il comando ortografico danno 1 per errore, a meno che l'errore non sia il risultato di un'autorizzazione negata, un file inesistente o un tentativo di leggere una directory. In uno di questi casi, escono 0 nonostante non riescano.

Quindi il comando expr fornisce 1 per successo a meno che l'output sia la stringa vuota o zero, nel qual caso 0 è successo. 2 e 3 sono guasti.

Quindi ci sono casi in cui il successo o il fallimento sono ambigui. Quando grep non riesce a trovare un modello, esce 1, ma esce 2 per un vero fallimento (come l'autorizzazione negata). Klist esce anche 1 quando non riesce a trovare un ticket, anche se questo non è in realtà un errore maggiore rispetto a quando grep non trova uno schema o quando si trova una directory vuota.

Quindi, sfortunatamente, i poteri unix che sembrano non imporre alcun insieme logico di regole, anche su eseguibili di uso molto comune.


Stavo per sottolineare anche il comportamento del diff. wget ha anche errori dettagliati (ad es. 6 per errore di autenticazione), ma poi usano 1 = errore generico, 2..n = errore specifico
PypeBros,

5

I programmi restituiscono un codice di uscita a 16 bit. Se il programma è stato interrotto con un segnale, il byte di ordine superiore contiene il segnale utilizzato, altrimenti il ​​byte di ordine inferiore è lo stato di uscita restituito dal programmatore.

Come viene assegnato quel codice di uscita alla variabile di stato $? dipende quindi dalla shell. Bash mantiene i 7 bit inferiori dello stato e quindi utilizza 128 + (segnale nr) per indicare un segnale.

L'unica convenzione "standard" per i programmi è 0 per esito positivo, diversa da zero per errore. Un'altra convenzione utilizzata è quella di restituire errno in caso di errore.


3

I codici di uscita Unix standard sono definiti da sysexits.h, come menzionato da un altro poster. Gli stessi codici di uscita sono utilizzati da librerie portatili come Poco - ecco un elenco di questi:

http://pocoproject.org/docs/Poco.Util.Application.html#16218

Un segnale 11 è un segnale SIGSEGV (violazione del segmento), che è diverso da un codice di ritorno. Questo segnale viene generato dal kernel in risposta a un accesso alla pagina errato, che causa la chiusura del programma. Un elenco di segnali è disponibile nella pagina man del segnale (esegui "man signal").


1

Quando Linux restituisce 0, significa successo. Qualsiasi altra cosa significa fallimento, ogni programma ha i suoi codici di uscita, quindi sarebbe abbastanza lungo elencarli tutti ...!

Circa l'11 codice di errore, è in effetti il ​​numero di errore di segmentazione, il che significa principalmente che il programma ha avuto accesso a una posizione di memoria che non è stata assegnata.


1
È sempre 11 perché il kernel lo uccide e assegna il "valore di uscita". Allo stesso modo, altri tipi di guasti avranno sempre lo stesso valore di uscita.
Alex Gartrell,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.