¿Qué significa `{ { (salida 1); salida 1; }; }` significa?

¿Qué significa `{ { (salida 1); salida 1; }; }` significa?

Cité el siguiente fragmento de código config.statusgenerado 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 exiten una subcapa?

Respuesta1

La ejecución (exit 1);es la forma más sencilla de activar una ERRtrampa. También provocará una salida inmediata si set -eestá en vigor. (Para activar la condición de error es necesario que falle un comando; exitcon 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 ERRtrampa, 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 autoconflos archivos. autoconfLos scripts dependen de la EXITtrampa para limpiar los archivos temporales creados durante la ejecución. La mayoría de los shells, incluido el que establece, bashestablecerán el estado a partir del valor proporcionado en el exitcomando antes de llamar a la EXITtrampa. Eso podría permitir que la EXITtrampa 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 delautoconfmanual:

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 la AC_MSG_ERRORmacro que tiene una solución alternativa para este problema.

La solución es asegurarse de que $?tenga el estado de salida.antesse ejecuta el exitcomando, por lo que definitivamente tendrá ese valor cuando EXITse ejecute la trampa. Y, de hecho, es la AC_MSG_ERRORmacro 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 1tiene 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 exitun subshell puede ser no salir del script (aunque se usa exit para generar un determinado código de salida).

información relacionada