Cité el siguiente fragmento de código config.status
generado por configure
.
if test ! -f "$as_myself"; then
{ { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
{ (exit 1); exit 1; }; }
fi
En el fragmento de código, ¿qué hace { (exit 1); exit 1; };
? ¿Cuál es el propósito de hacerlo solo exit
en una subcapa?
Respuesta1
La ejecución (exit 1);
es la forma más sencilla de activar una ERR
trampa. También provocará una salida inmediata si set -e
está en vigor. (Para activar la condición de error es necesario que falle un comando; exit
con un valor de error en un subshell, el subshell falla).
exit 1;
No hará ninguna de esas cosas.
So {(exit 1); exit 1;}
puede usarse para producir primero la ERR
trampa, que podría hacer algo útil para fines de depuración, y luego finalizar el script con una indicación de error.
Pero eso no es lo que sucede en autoconf
los archivos. autoconf
Los scripts dependen de la EXIT
trampa para limpiar los archivos temporales creados durante la ejecución. La mayoría de los shells, incluido el que establece, bash
establecerán el estado a partir del valor proporcionado en el exit
comando antes de llamar a la EXIT
trampa. Eso podría permitir que la EXIT
trampa detecte si fue invocada por un error o por una terminación normal, y también le permite garantizar que el estado de salida esté configurado correctamente al final de la operación de la trampa.
Sin embargo, aparentemente algunas conchas no cooperan. Aquí hay una cita delautoconf
manual:
Algunos scripts de shell, como los generados por
autoconf
, utilizan una trampa para limpiar antes de salir. Si el último comando de shell salió con un estado distinto de cero, la trampa también sale con un estado distinto de cero para que el invocador pueda saber que ocurrió un error.Desafortunadamente, en algunos shells, como Solaris
/bin/sh
, una trampa de salida ignora el argumento del comando de salida. En estos shells, una trampa no puede determinar si fue invocada por la salida simple o por la salida 1. En lugar de llamar a la salida directamente, use laAC_MSG_ERROR
macro que tiene una solución alternativa para este problema.
La solución es asegurarse de que $?
tenga el estado de salida.antesse ejecuta el exit
comando, por lo que definitivamente tendrá ese valor cuando EXIT
se ejecute la trampa. Y, de hecho, es la AC_MSG_ERROR
macro la que inserta ese código curioso, completo con llaves redundantes.
Respuesta2
Por lo que puedo ver, no hay ningún propósito para esto, no hay nada que se pueda lograr directamente iniciando una subcapa y luego saliendo inmediatamente.
Lo más probable es que cosas como esta sean un efecto secundario de la generación automática de código; en algunos casos, puede haber otros comandos ejecutados en el subshell donde tener sentido exit 1
tiene sentido. En última instancia, existe una buena posibilidad de que la generación de código se simplifique de alguna manera al permitirle insertar algunas declaraciones que no tienen ninguna función en algunos casos y generar un "código limpio" cada vez es más complejo. O eso o el código que generó lo anterior está mal escrito :)
El uso liberal de {...}
es otro ejemplo de esto, la mayoría de ellos son redundantes, pero es más fácil escribir código que los inserte en todos los casos (tal vez en algunos quieras redirigir la salida/entrada del bloque) en lugar de distinguir los aquellos en los que no son necesarios y omitirlos.
Respuesta3
(exit 1)
es una forma sencilla, probablemente la más sencilla, de obtener un determinado código de salida (en el caso especial de 1, hay formas más sencillas, por supuesto). Pero en este caso ese no es el motivo, ya que no se examina el código de salida.
El propósito de colocar exit
un subshell puede ser no salir del script (aunque se usa exit para generar un determinado código de salida).