ver tuberias salida redireccionamiento procesos por operador mensajes los guardar generados filtros error envían ejemplos dónde defecto corriendo comandos comando archivo linux error-handling exit-code

tuberias - ¿Hay códigos de estado de salida estándar en Linux?



ver procesos corriendo en linux (10)

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 dan como resultado un estado de salida de 11, aunque no sé si esto es simplemente la convención donde trabajo (las aplicaciones que fallaron así han sido todas internas) o un estándar.

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


Parte 1: Guía avanzada de scripts de Bash

Como siempre, la Guía de scripts de Advanced Bash tiene una gran 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 shell construidos (según la documentación de Bash)
126: Comando invocado no se puede ejecutar
127: "comando no encontrado"
128: argumento inválido para salir
128 + n: señal de error fatal "n"
255: Estado de salida fuera de rango (la salida toma solo argumentos enteros en el rango de 0 a 255)

Parte 2: sysexits.h

La ABSG hace referencia a 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 */


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

Sobre el código de error 11, es de hecho el número de falla de la segmentación, principalmente porque el programa accedió a una ubicación de memoria que no fue asignada.


Los códigos de salida estándar de Unix están definidos por sysexits.h, como se menciona en otro póster. Los mismos códigos de salida son utilizados por las bibliotecas portátiles como Poco, 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 kernel en respuesta a un acceso de página defectuoso, lo que hace que el programa termine. Se puede encontrar una lista de señales en la página del comando man (ejecutar "man signal").


Los programas devuelven un código de salida de 16 bits. Si el programa se eliminó con una señal, 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 $? es entonces hasta la cáscara. Bash mantiene los 7 bits más bajos 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 éxito, no cero para error. Otra convención utilizada es devolver errno en error.


Ninguna de las respuestas anteriores describe el estado de salida 2 correctamente. Contrariamente a lo que afirman, el estado 2 es lo que realmente devuelven las utilidades de la línea de comandos cuando se llaman incorrectamente. (Sí, una respuesta puede tener nueve años, tener cientos de upvotes y aún estar equivocada).

Esta es la convención de estado de salida real y de larga duración 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, diff devuelve 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 de argumentos incorrectos, etc.) Por ejemplo, diff -N , grep -Y o diff abc darán como resultado $? estableciéndose en 2. Esta es y ha sido la práctica desde los 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 capturada 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 indebido de elementos bash". Esto se aplica solo cuando bash (o un script bash) sale con el estado 2. Considérelo como 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 tengo conocimiento de ninguna utilidad común de Unix que devuelva 64 en incorrecto invocación (ejemplos bienvenidos). La lectura cuidadosa del código fuente revela que sysexits.h es aspiracional, en lugar de un reflejo del verdadero uso:

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


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

stdlib.h define EXIT_FAILURE como 1 y EXIT_SUCCESS como 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 detener el proceso en caso de un segfault. Es probable que exista algún mecanismo, ya sea en el kernel o en el shell, que lo traduzca en el código de salida.


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

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

El comando diff da 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 error a menos que no proporcione un argumento, en cuyo caso, sale de 0 a pesar de fallar.

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

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

Luego hay casos donde el éxito o el fracaso es ambiguo. Cuando grep no encuentra un patrón, sale de 1, pero sale de 2 por una falla genuina (como permiso denegado). Klist también sale de 1 cuando no puede encontrar un ticket, aunque esto no es realmente un fracaso más que cuando grep no encuentra un patrón, o cuando se trata de un directorio vacío.

Así que, desafortunadamente, los poderes de Unix que parecen no imponen ningún conjunto lógico de reglas, incluso en ejecutables de uso común.


8 bits del código de retorno y 8 bits del número de la señal de desactivació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 forma anormal.

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

Si está viendo algo que no sea esto, entonces el programa probablemente tenga un controlador de señales SIGSEGV que luego exit normalmente, por lo que la señal no lo mata. (Los programas pueden elegir manejar cualquier señal aparte de SIGKILL y SIGSTOP ).


''1'' >>> Catchall para errores generales

''2'' >>> Uso incorrecto de los shell construidos (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"

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

''255'' >>> Salir del estado fuera de rango

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


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

Desde la página man de OpenBSD:

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