¿Hay algún código de estado de salida estándar en Linux?

308

Se considera que un proceso se ha completado correctamente en Linux si su estado de salida era 0.

He visto que las fallas de segmentación a menudo resultan en un estado de salida de 11, aunque no sé si esta es simplemente la convención en la que trabajo (las aplicaciones que fallaron así han sido internas) o un estándar.

¿Existen códigos de salida estándar para procesos en Linux?

Nathan Fellman
fuente
66
si está buscando lo que se llama "número de error del sistema" devuelto por las funciones del sistema, vea aquí en errno
marinara

Respuestas:

86

8 bits del código de retorno y 8 bits del número de la señal de eliminación se mezclan en un solo valor en el retorno 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" */
}

¿Cómo estás determinando el estado de salida? Tradicionalmente, el shell solo almacena un código de retorno de 8 bits, pero establece el bit alto si el proceso finalizó de manera anormal.

$ sh -c 'salida 42'; echo $?
42
$ sh -c 'kill -SEGV $$'; echo $?
Fallo de segmentación
139
$ expr 139-128
11

Si ve algo más que esto, entonces el programa probablemente tenga un SIGSEGVcontrolador de señal que luego llama exitnormalmente, por lo que la señal no lo mata. (Los programas pueden elegir manejar cualquier señal aparte de SIGKILLy SIGSTOP.)

efímero
fuente
8
Dada la forma en que aparece ahora la pregunta, esta no parece ser la respuesta más útil (y por lo tanto aceptada).
David J.
332

Parte 1: Guía avanzada de secuencias de comandos Bash

Como siempre, la Guía avanzada de secuencias de comandos de Bash tiene excelente información : (Esto estaba vinculado en otra respuesta, pero a una URL no canónica).

1: Catchall para errores generales
2: Uso incorrecto de los componentes de shell (según la documentación de Bash)
126: El comando invocado no puede ejecutarse
127: "comando no encontrado"
128: Argumento no válido para salir
128 + n: Señal de error fatal "n"
255: Salir estado fuera de rango (la salida solo toma argumentos enteros en el rango de 0 a 255)

Parte 2: sysexits.h

Las referencias de ABSG sysexits.h.

En 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
fuente
55
Tenga en cuenta que en algunos tipos de Unix, algunos comandos usan un estado de salida de 2 para indicar otras cosas. Por ejemplo, muchas implementaciones de grep usan un estado de salida de 2 para indicar un error, y usan un estado de salida de 1 para indicar que no se encontraron líneas seleccionadas.
NamshubWriter
3
En BSD hay una página de manual que resume la información de sysexits.h:man sysexits
georgebrock
66
Lo que dijo @NamshubWriter. El estado de salida 2 es el recurso universal para el uso incorrecto de la línea de comandos en las utilidades de Unix, no solo en "algunos sabores de Unix" sino en general. El encabezado que se muestra en esta respuesta no refleja las convenciones reales, ahora o cuando fue escrito en 1987.
alexis
El ABS no es "genial". Por favor lea sobre el tema; No es exactamente difícil encontrar críticas.
tripleee
Pero, ¿dónde está el código fuente oficial real sysexits.h? La página de manual que todo el mundo hace referencia es solo prosa. Por ejemplo, hace referencia, EX_OKpero en realidad no lo define de una manera normativa como los otros códigos. ¿Hay más que faltan?
Garret Wilson
71

'1' >>> Catchall para errores generales

'2' >>> Uso indebido de los componentes integrados de shell (según la documentación de Bash)

'126' >>> El comando invocado no se puede ejecutar

'127' >>> "comando no encontrado"

'128' >>> Argumento no válido para salir

'128 + n' >>> Señal de error fatal "n"

'130' >>> Script terminado por Control-C

'255' >>> Estado de salida fuera de rango

Esto es para bash. Sin embargo, para otras aplicaciones, hay diferentes códigos de salida.

segfault
fuente
1
Parece que ambos respondieron en el mismo minuto. Tian tendría que ser bastante rápido para ver sus enlaces y pegarlos en.
Nathan Fellman
66
Tenga en cuenta que 'control-C produce 130' es consistente con '128 + n' para la señal n; control-C genera SIGINT que es la señal 2.
Jonathan Leffler
3
Esto parece ser plagiado del ABS sin atribución. (Podemos decirlo porque el ABS contiene información incorrecta o al menos engañosa).
tripleee
44
Estos son códigos de salida RESERVADOS, de acuerdo con la Guía avanzada de secuencias de comandos Bash . Eso significa que estos valores deben evitarse para los parámetros de salida especificados por el usuario .
ingyhere
53

Ninguna de las respuestas anteriores describe el estado de salida 2 correctamente. Al contrario de lo que afirman, el estado 2 es lo que sus utilidades de línea de comando realmente devuelven cuando se les llama incorrectamente. (Sí, una respuesta puede tener nueve años, tener cientos de votos a favor y aún estar equivocado).

Aquí está la convención de estado de salida real y de larga data para la terminación normal, es decir, no por señal:

  • Estado de salida 0: éxito
  • Estado de salida 1: "falla", como lo define el programa
  • Estado de salida 2: error de uso de línea de comando

Por ejemplo, diffdevuelve 0 si los archivos que compara son idénticos y 1 si difieren. Por convención de larga data, los programas de Unix devuelven el estado de salida 2 cuando se los llama incorrectamente (opciones desconocidas, número incorrecto de argumentos, etc.) Por ejemplo diff -N, grep -Yo diff a b ctodo resultará en $?establecerse en 2. Esta es y ha sido la práctica desde primeros días de Unix en la década de 1970.

La respuesta aceptada explica qué sucede cuando un comando termina con una señal. En resumen, la terminación debido a una señal no detectada da como resultado el estado de salida 128+[<signal number>. Por ejemplo, la terminación por SIGINT( señal 2 ) da como resultado el estado de salida 130.

Notas

  1. Varias respuestas definen el estado de salida 2 como "Uso incorrecto de bash builtins". Esto se aplica solo cuando bash (o un script bash) sale con el estado 2. Considere un caso especial de error de uso incorrecto.

  2. En sysexits.h, mencionado en la respuesta más popular , el estado de salida EX_USAGE("error de uso de la línea de comandos") se define como 64. Pero esto no refleja la realidad: no conozco ninguna utilidad común de Unix que devuelva 64 en una invocación incorrecta (se aceptan ejemplos ) La lectura cuidadosa del código fuente revela que sysexits.hes aspiracional, más que un reflejo del uso verdadero:

     *    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 otras palabras, estas definiciones no reflejan la práctica común en ese momento (1993) pero fueron intencionalmente incompatibles con ella. Más es la pena.

alexis
fuente
¿Qué le debo un retorno programa cuando se hace la terminación mango por la captura de SIGINT / Ctrl-C? Todavía 130? ¿El uso de otro shell además de bash importa?
Gringo Suave
1
El shell que ejecuta el programa es irrelevante; un proceso teóricamente podría elegir salir con un estado diferente dependiendo de su proceso padre, pero nunca he oído hablar de un caso en el que esto suceda.
alexis
1
Si un programa detecta SIGINT, limpia y sale de todos modos, el estado es lo que tenga sentido para el programa. Por ejemplo, morerestablecerá los modos del terminal y saldrá con el estado 0 (puede probarlo).
alexis
1
Esta respuesta implica un grado de estandarización mucho mayor que el que realmente es el caso. No existe una estandarización adecuada del significado del valor 2, y la práctica real es entonces previsiblemente muy variada. Es cierto que muchas herramientas devuelven 2 por uso incorrecto, pero no está exactamente bien definido qué significa "uso incorrecto", y muchas otras no se adhieren a esta convención.
tripleee
¡Las "herramientas" de @tripleee tampoco están bien definidas! :-) Claro, cualquiera puede escribir un programa de línea de comandos y puede devolver cualquier cosa, pero las "utilidades de línea de comandos Unix" de la vieja escuela que han existido por más tiempo que Linux, o los contenidos de GNU coreutils, son bastante consistente en esto. Si piensa lo contrario, nombre algunas herramientas en este grupo que no usen el estado 2 de esta manera. Además, "uso inapropiado" es su término (y estoy de acuerdo en que es un término vago); Escribí "error de uso de la línea de comandos", que es bastante específico: opciones inexistentes o incompatibles, número incorrecto de argumentos no opcionales, etc.
alexis
25

No hay códigos de salida estándar, aparte de 0 que significa éxito. No cero tampoco significa necesariamente un fracaso.

stdlib.h define EXIT_FAILUREcomo 1 y EXIT_SUCCESScomo 0, pero eso es todo.

El 11 en segfault es interesante, ya que 11 es el número de señal que el kernel usa para matar el proceso en caso de un segfault. Es probable que haya algún mecanismo, ya sea en el núcleo o en el shell, que se traduzca en el código de salida.

Chris Arguin
fuente
20

sysexits.h tiene una lista de códigos de salida estándar. Parece que se remonta al menos a 1993 y algunos grandes proyectos como Postfix lo usan, así que imagino que es el camino a seguir.

Desde la página de manual de OpenBSD:

Según el estilo (9), no es una buena práctica llamar a la salida (3) con valores arbitrarios para indicar una condición de falla al finalizar un programa. En su lugar, se deben utilizar los códigos de salida predefinidos de sysexits, de modo que el llamante del proceso pueda obtener una estimación aproximada de la clase de falla sin buscar el código fuente.

fuente
8

Para una primera aproximación, 0 es éxito, no cero es falla, siendo 1 una falla general y cualquier cosa mayor que uno es una falla específica. Aparte de las excepciones triviales de falso y prueba, que están diseñadas para dar 1 por éxito, encontré algunas otras excepciones.

De manera más realista, 0 significa éxito o tal vez falla, 1 significa falla general o tal vez éxito, 2 significa falla general si 1 y 0 se usan para el éxito, pero tal vez también el éxito.

El comando diff proporciona 0 si los archivos comparados son idénticos, 1 si difieren y 2 si los binarios son diferentes. 2 también significa fracaso. El comando less da 1 por falla a menos que no proporcione un argumento, en cuyo caso, sale de 0 a pesar de fallar.

El comando more y el comando de deletreo dan 1 por falla, a menos que la falla sea el resultado de un permiso denegado, un archivo inexistente o un intento de leer un directorio. En cualquiera de estos casos, salen de 0 a pesar de fallar.

Luego, el comando expr da 1 para el éxito a menos que la salida sea la cadena vacía o cero, en cuyo caso, 0 es el éxito. 2 y 3 son fracaso.

Luego hay casos en los que el éxito o el fracaso son ambiguos. Cuando grep no puede encontrar un patrón, sale 1, pero sale 2 por una falla genuina (como permiso denegado). Klist también sale 1 cuando no puede encontrar un ticket, aunque esto no es realmente un error mayor que cuando grep no encuentra un patrón o cuando es un directorio vacío.

Entonces, desafortunadamente, los poderes de Unix que parecen no imponen ningún conjunto lógico de reglas, incluso en ejecutables muy comúnmente utilizados.

Frederick
fuente
Estaba a punto de señalar el comportamiento de diff también. wget también tiene errores detallados (por ejemplo, 6 por falla de autenticación), pero luego usan 1 = error genérico, 2..n = error específico
PypeBros
5

Los programas devuelven un código de salida de 16 bits. Si el programa fue eliminado con una señal, entonces el byte de orden superior contiene la señal utilizada; de lo contrario, el byte de orden inferior es el estado de salida devuelto por el programador.

¿Cómo se asigna ese código de salida a la variable de estado $? entonces depende del caparazón. Bash mantiene los 7 bits inferiores del estado y luego usa 128 + (señal nr) para indicar una señal.

La única convención "estándar" para los programas es 0 para el éxito, no cero para el error. Otra convención utilizada es devolver errno en caso de error.

Dean Povey
fuente
3

Los códigos de salida estándar de Unix están definidos por sysexits.h, como se menciona en otro póster. Las bibliotecas portátiles, como Poco, usan los mismos códigos de salida. Aquí hay una lista de ellos:

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

Una señal 11 es una señal SIGSEGV (violación de segmento), que es diferente de un código de retorno. Esta señal es generada por el núcleo en respuesta a un mal acceso a la página, lo que hace que el programa finalice. Puede encontrar una lista de señales en la página de manual de señales (ejecute "señal de hombre").

Daniel Schuler
fuente
1

Cuando Linux devuelve 0, significa éxito. Cualquier otra cosa significa falla, cada programa tiene sus propios códigos de salida, ¡así que sería bastante largo enumerarlos a todos ...!

Acerca del código de error 11, de hecho es el número de falla de segmentación, lo que significa que el programa accedió a una ubicación de memoria que no fue asignada.

Amadeus45
fuente
1
Siempre es 11 porque el núcleo lo mata y asigna el "valor de salida". Del mismo modo, otros tipos de fallas siempre obtendrán el mismo valor de salida.
Alex Gartrell