Esistono codici di stato di uscita standard in Linux?
-
12-09-2019 - |
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?
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
-
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.
-
In
sysexits.h
, citato nella risposta più popolare , stato di uscitaEX_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 chesysexits.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 other 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.