Domanda

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

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

Esistono codici di uscita standard per i processi in Linux?

È stato utile?

Soluzione

8 bit del codice di ritorno e 8 bit del numero del segnale di abbattimento sono miscelati in un singolo valore al ritorno dalla 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 stai determinando lo stato di uscita? Tradizionalmente, il guscio memorizza solo un codice di ritorno 8 bit, ma imposta il bit alto se il processo è terminata in modo anomalo.

$ sh -c 'exit 42'; echo $?
42
$ sh -c 'kill -SEGV $$'; echo $?
Segmentation fault
139
$ expr 139 - 128
11

Se stai vedendo qualcosa di diverso da questo, allora il programma ha probabilmente un gestore di segnale SIGSEGV che poi chiama exit normalmente, in modo che non è in realtà sempre ucciso dal segnale. (I programmi possono scegliere di gestire eventuali segnali parte SIGKILL e SIGSTOP.)

Altri suggerimenti

Parte 1: avanzata di Bash Scripting Guide

Come sempre, avanzata Bash Scripting Guide ha informazioni :  (Questo è stato collegato in un'altra risposta, ma a un URL non canonico.)

  

1 Indica errori generici
   2: Abuso di builtin di shell (secondo la documentazione Bash)
   126: Comando invocato non può eseguire
   127: "command not found"
   128: Argomento non valido per uscire
   128 + n: segnale di errore fatale "n"
   255: Esci stato di fuori campo (uscita prende argomento solo un intero nel range 0 - 255)

Parte 2: sysexits.h

L'ABSG riferimenti sysexits.h.

In 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' >>> Indica errori generici

'2' >>> Sviamento di builtin di shell (secondo la documentazione Bash)

'126' >>> comando invocato non può eseguire

'127' >>> "command not found"

'128' >>> argomento valido per uscire

'128 + n' >>> segnale di errore fatale "n"

'130' >>> Script denuncia da parte di Control-C

'255' >>> uscita fuori campo

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

Nessuna delle risposte più anziani descrivere lo stato di uscita 2 in modo corretto. Contrariamente a quanto affermano, Stato 2 è quello che le utilità della riga di comando in realtà restituiscono quando viene chiamato impropriamente. (Sì, una risposta può essere nove anni, hanno centinaia di upvotes, ed ancora essere sbagliato.)

Ecco il vero, a lungo in piedi Convenzione stato di uscita per la terminazione normale, cioè non dal segnale:

  • Lo stato d'uscita 0: successo
  • Stato uscita 1: "fallimento", come definito dal programma
  • Exit status 2: comando di errore di utilizzo riga

Per esempio, diff restituisce 0 se i file si confronta sono identici, e 1 in caso contrario. Per convenzione di lunga data, programmi Unix ritorno stato d'uscita 2 quando viene chiamato in modo non corretto (opzioni sconosciuti, numero errato di argomenti, ecc.) Ad esempio, diff -N, grep -Y o diff a b c saranno tutti risultato $? essere impostato su 2. Questo è ed è stata la prassi fin dai primi giorni di Unix nel 1970.

La risposta accettata spiega cosa succede quando un comando è terminato da un segnale. In Insomma, la terminazione a causa di un non gestite fanno i risultati dei segnali in stato di uscita 128+[<signal number>. Ad esempio, risoluzione da parte di SIGINT ( segnale 2 ) risultati in stato di uscita 130.

Note

  1. Diverse risposte definiscono lo stato di uscita 2 come "uso improprio di builtin bash". Questo vale solo quando bash (o uno script bash) esce con lo stato 2. considerarlo un caso speciale di errore di uso scorretto.

  2. In sysexits.h , citato nella risposta più popolare , stato di uscita EX_USAGE ( "linea di errore di utilizzo di comando") è definito come 64. Ma questo non riflette la realtà: io non sono a conoscenza di qualsiasi utility comune Unix che ritorna 64 su invocazione non corretta (esempi benvenuto). Una lettura attenta del rivela che sysexits.h è aspirazionale, piuttosto che un riflesso di utilizzo vero :

     *    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 a quel tempo (1993), ma sono stati intenzionalmente incompatibili con esso. Più è la pietà.

Non ci sono codici di uscita standard, oltre a 0 che significa successo. Non-zero non significa necessariamente il fallimento sia.

stdlib.h fa definire EXIT_FAILURE come 1 e EXIT_SUCCESS come 0, ma che su di esso.

Il 11 sul segfault è interessante, come 11 è il numero di segnale che il kernel usa per uccidere il processo in caso di un segfault. V'è probabile che qualche meccanismo, sia nel kernel o nel guscio, che si traduce che nel codice di uscita.

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

Dalla pagina man OpenBSD:

Secondo lo stile (9), non è buona pratica di chiamare exit (3) con compromissoria valori contrariamente a indicare una condizione di errore quando si termina un programma. Nel- vece, i codici di uscita predefiniti da sysexits dovrebbero essere usati, per cui la chiamante del processo può ottenere una stima approssimativa sulla classe fallimento senza alzare lo sguardo al codice sorgente.

In prima approssimazione, 0 è sucess, diverso da zero è guasto, con 1 è guasto generale, e nulla più grande di uno è un guasto specifico. A parte le eccezioni banali di falso e di prova, che sono entrambi progettati per dare 1 per sucesso, ci sono alcune altre eccezioni che ho trovato.

Più realisticamente, 0 significa sucess o forse guasto, 1 significa guasto generale o forse sucess, 2 significa errore generale se 1 e 0 vengono entrambi utilizzati per sucess, ma forse Sucess pure.

Il comando diff dà 0 se i file confrontati sono identici, 1 in caso contrario, e 2 se binari sono differenti. 2 significa anche il fallimento. Il comando di meno dà 1 per il fallimento a meno che non si riesce a fornire un argomento, in questo caso, esce 0 nonostante fallendo.

Il comando sempre il comando incantesimo danno 1 per il fallimento, a meno che il fallimento è il risultato di permesso negato, file inesistente, o tentare di leggere una directory. In ognuno di questi casi, escono 0 nonostante fallendo.

Poi il comando expr dà 1 per sucess meno che l'uscita è la stringa vuota o zero, nel qual caso, 0 è sucess. 2 e 3 sono guasti.

Poi c'è casi in cui successo o il fallimento è ambigua. Quando grep non riesce a trovare un modello, esce 1, ma esce 2 per un guasto vero e proprio (come permesso negato). Klist esce anche 1 quando non riesce a trovare un biglietto, anche se questo non è in realtà più di un fallimento rispetto a quando grep non trova un modello, o quando si ls una directory vuota.

Così, purtroppo, i poteri che essere Unix non sembrano imporre qualsiasi insieme logico di regole, anche su eseguibili molto comunemente usati.

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

Come viene assegnato il codice di uscita alla variabile di stato $?tocca quindi al guscio.Bash mantiene i 7 bit inferiori dello stato e quindi utilizza 128 + (n. segnale) per indicare un segnale.

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

codici di uscita standard Unix sono definiti da sysexits.h, come un altro manifesto menzionato. Gli stessi codici di uscita sono utilizzate da librerie portatili come Poco - ecco un elenco di loro:

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

Un segnale 11 è un segnale SIGSEGV (violazione segmento), che è diverso da un codice di ritorno. Questo segnale viene generato dal kernel in risposta ad una cattiva accesso pagina, che fa sì che il programma per terminare. Un elenco dei segnali si possono trovare nella pagina man signal (eseguire "segnale man").

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

Per quanto riguarda il codice di errore 11, si tratta in effetti del numero di errore di segmentazione, che significa principalmente che il programma ha avuto accesso a una posizione di memoria che non era stata assegnata.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top