Recientemente me encontré con esta lista de Códigos de salida con significados especiales de la Guía avanzada de secuencias de comandos Bash. Se refieren a estos códigos como reservados y recomiendan que:
De acuerdo con la tabla anterior, los códigos de salida 1-2, 126-165 y 255 tienen significados especiales y, por lo tanto, deben evitarse para los parámetros de salida especificados por el usuario.
Hace un tiempo, escribí un script que usaba los siguientes códigos de estado de salida:
- 0 - éxito
- 1 - nombre de host incorrecto
- 2 - argumentos no válidos especificados
- 3 - privilegios de usuario insuficientes
Cuando escribí el script no tenía conocimiento de ningún código de salida especial, así que simplemente comencé en 1 para la primera condición de error e incrementé el estado de salida para cada tipo de error sucesivo.
Escribí el script con la intención de que en una etapa posterior pudiera ser invocado por otros scripts (que podrían verificar los códigos de salida distintos de cero). En realidad no he hecho eso todavía; Hasta ahora solo he ejecutado el script desde mi shell interactivo (Bash) y me preguntaba qué / si algún problema podría ser causado al usar mis códigos de salida personalizados. ¿Cuán relevante / importante es la recomendación de la Guía avanzada de secuencias de comandos Bash?
No pude encontrar ningún consejo que corroborara en la documentación de Bash; su sección sobre el estado de salida simplemente enumera los códigos de salida utilizados por Bash, pero no indica que ninguno de estos esté reservado ni advierta contra su uso para sus propios scripts / programas.
fuente
Respuestas:
Ha habido varios intentos de estandarizar los significados de los códigos de salida del proceso. Además del que mencionas, sé de:
los BSD tienen
sysexits.h
que define significados para valores desde 64 en adelante.Los
grep
documentos de GNU que indican que el código de salida 0 significa que se encontró al menos una coincidencia, 1 significa que no se encontraron coincidencias y 2 significa que se produjo un error de E / S; esta convención obviamente también es útil para otros programas para los cuales la distinción entre "nada salió mal pero no encontré nada" y "ocurrió un error de E / S" es significativa.Muchas implementaciones de la función de biblioteca C
system
usan el código de salida 127 para indicar que el programa no existe o no pudo iniciarse.En Windows, los
NTSTATUS
códigos (que están convenientemente dispersos por todo el espacio de números de 32 bits) pueden usarse como códigos de salida, particularmente los que indican que un proceso se terminó debido a un mal comportamiento catastrófico (por ejemploSTATUS_STACK_OVERFLOW
).No puede contar con que un programa determinado obedezca una de estas convenciones en particular. La única regla confiable es que el código de salida 0 es exitoso y cualquier otra cosa es algún tipo de falla. (Tenga en cuenta que de C89
EXIT_SUCCESS
se no garantiza tener el valor cero, sin embargo,exit(0)
se requiere que se comporten de forma idéntica alexit(EXIT_SUCCESS)
., Incluso si los valores no son los mismos)fuente
Ningún código de salida tiene un significado especial, pero el valor en
$?
puede tener un significado especial.El problema es la forma en que Bourne Shell y ksh93 manejaron y enviaron códigos de salida y situaciones de error a la variable de shell
$?
. Al contrario de lo que enumera, solo los siguientes valores$?
tienen un significado especial:Además, hay un rango de
$?
códigos específicos de la plataforma y de la plataforma no especificados > 128 que está reservado para un programa que fue interrumpido por una señal:Otros valores no dan problemas, ya que pueden distinguirse de los
$?
valores especiales de shell .En particular, los valores 1 y 2 no se usan para condiciones especiales, sino que son solo códigos de salida utilizados por comandos incorporados que podrían actuar de la misma manera cuando no están incorporados. Parece que el puntero a la guía de scripts de bash que proporcionó no es un buen manual, ya que solo enumera los códigos utilizados por bash sin comentar si un código específico es un valor especial que debe evitarse para los propios scripts.
Las versiones más nuevas de Bourne Shell usan en
waitid()
lugar dewaitpid()
esperar a que el programa salga ywaitid()
(introducido en 1989 para SVr4) usa una mejor interfaz syscall (similar a lo que UNOS usaba en 1980).Como las versiones más recientes de Bourne Shell codifican el motivo de salida en una variable separada
${.sh.code}
/${.sh.codename}
que el código de salida que está en${.sh.status}
/${.sh.termsig}
, consulte http://schillix.sourceforge.net/man/man1/bosh.1.html , el código de salida no se sobrecarga con estados especiales y, como resultado del uso de `waitid (), Bourne Shell ahora admite la devolución de los 32 bits del código de salida, no solo los 8 bits bajos.Por cierto: tenga cuidado de no ser
exit(256)
similar a un programa C o script de shell, ya que esto$?
se interpreta como 0 en un shell clásico.fuente
waitid()
error a fines de mayo. La gente de FreeBSD solucionó el problema en 20 horas, la gente de Linux no está interesada en corregir su error. ... y la gente Cygwin dice que son bug por error Linux compatible ;-)_exit
. Por favor, vincule el informe de errores de FreeBSD al que se refiere, tal vez estoy malinterpretando el problema que describe.${.sh.}
variables. Sin embargo, es cierto que usted dice "Bourne" y no "derivado de Bourne" (aunque sí incluye ksh93)./bin/sh
se puede confiar en que se comportará de manera consistente con estos códigos de salida especiales multiplataforma, lo cual no es cierto. (No me importa si/bin/sh
se puede decir que algún sistema en particular sea un "shell Bourne real". Es mucho más importante saber que nada de esto está en POSIX, y que la mayoría de las cosas que usted cita como "sistemas Unix reales" no t proporcione un POSIX compatible de/bin/sh
todos modos.)Para las secuencias de comandos de shell, a veces incluyo en la fuente el equivalente de
sysexist.h
shell con códigos de salida reservados con shell (con el prefijoS_EX_
), que he denominadoexit.sh
Básicamente es:
Y se puede generar con:
Sin embargo, no lo uso mucho, pero lo que sí uso es una función de shell que invierte los códigos de error en sus formatos de cadena. He nombrado él
exit2str
. Suponiendo que haya nombrado elexit.sh
generador anteriorexit.sh.sh
, el código paraexit2str
se puede generar con (exit2str.sh.sh
):Lo uso en
PS1
mi shell interactivo para que después de cada comando que ejecuto, pueda ver su estado de salida y su forma de cadena (si tiene una forma de cadena conocida):Para obtener estos, necesita un insourcable para la función exit2str:
y luego úselo en su
~/.bashrc
para guardar y traducir el código de salida en cada símbolo del sistema y mostrarlo en su indicador (PS1
):Es bastante útil para observar cómo algunos programas siguen las convenciones del código de salida y otros no, para aprender acerca de las convenciones del código de salida, o simplemente para poder ver qué sucede más fácilmente. Después de haberlo usado durante algún tiempo, puedo decir que muchos scripts de shell orientados al sistema siguen las convenciones.
EX_USAGE
Es particularmente bastante común, aunque otros códigos, no mucho. Trato de seguir las convenciones de vez en cuando, aunque siempre hay$S_EX_ANY
(1) para gente perezosa (yo soy uno).fuente
Siempre que documente sus códigos de salida para que los recuerde dentro de un año, cuando tenga que regresar y modificar el script, estará bien. La idea de "códigos de salida reservados" realmente no se aplica más que decir que es costumbre usarla
0
como código de éxito y cualquier otra cosa como código de falla.fuente
La mejor referencia que pude encontrar fue esta: http://tldp.org/LDP/abs/html/exitcodes.html
De acuerdo a esto:
1
es una trampa general para los errores, y siempre he visto que se usa para errores definidos por el usuario.2
es por mal uso de los complementos integrados de shell, como un error de sintaxisPara responder su pregunta directamente, su script estará bien usando los códigos de error reservados, funcionará como se espera, suponiendo que maneje el error en función del código de error = 1/2/3.
Sin embargo, posiblemente sería confuso si se encuentra con alguien que conozca y use los códigos de error reservados, lo que parece bastante raro.
Otra opción disponible para usted es hacer eco del error si hay uno y luego salir, suponiendo que su script siga la convención de Linux de "ninguna noticia es una buena noticia" y echo no es nada exitoso.
fuente
Según las respuestas que recibí (fue difícil elegir una sobre las otras), no es dañino indicar ciertos tipos de errores al usar un código de salida que Bash también usa. Bash (o cualquier otro shell de Unix) no hará nada especial (como ejecutar controladores de excepciones) si una secuencia de comandos de usuario sale con uno de estos códigos de error.
Parece que el autor de la Guía avanzada de secuencias de comandos Bash está de acuerdo con los intentos de BSD de estandarizar los códigos de salida (
sysexits.h
) y simplemente recomienda que cuando los usuarios escriben scripts de shell, no especifiquen códigos de salida que ya entren en conflicto con los códigos de salida predefinidos en uso, es decir, restringen sus códigos de salida personalizados a los 50 códigos de estado disponibles en el rango 64-113.Aprecio la idea (y la justificación) pero hubiera preferido que el autor fuera más explícito que no es dañino ignorar el consejo, aparte de los casos en que el consumidor de un guión está buscando errores, como el ejemplo citado de 127 (
command not found
)Especificaciones POSIX relevantes
Investigué lo que POSIX tiene que decir sobre los códigos de salida y la especificación POSIX parece estar de acuerdo con el autor de la Guía Avanzada de Bash-Scripting. He citado las especificaciones POSIX relevantes (énfasis mío):
Estado de salida para comandos
La
exit
utilidadMás información
Por lo que vale, pude verificar todos menos uno de la lista de Códigos de salida con significados especiales . Esta tabla de códigos de salida es útil ya que proporciona más detalles y ejemplos de cómo generar los códigos de error documentados en la referencia de Bash .
Intenta generar un estado de salida de 128
Usando las versiones Bash 3.2.25 y 4.2.46, traté de arrojar un
128 Invalid argument to exit
error, pero cada vez que recibí un 255 (estado de salida fuera de rango). Por ejemplo, siexit 3.14159
se ejecuta como parte de un script de shell o en un shell secundario interactivo, el shell sale con un código de255
:Para divertirme aún más, también intenté ejecutar un programa C simple, pero en este caso, parece que la
exit(3)
función simplemente convirtió el flotador en int (3 en este caso) antes de salir:fuente