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

28

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 hacer solo exiten una subshell?

MS.Kim
fuente

Respuestas:

33

La ejecución (exit 1);es la forma más sencilla de activar una ERRtrampa. También activará la salida inmediata si set -eestá vigente. (La activación de la condición de error requiere que falle un comando; exitcon un valor de falla en una subshell, la subshell falla).

exit 1; no hará ninguna de esas cosas.

Por {(exit 1); exit 1;}lo tanto, se puede usar para producir primero la ERRtrampa, que podría hacer algo útil para fines de depuración, y luego terminar el script con una indicación de error.

Pero eso no es lo que está sucediendo en los autoconfarchivos. autoconflos scripts se basan en la EXITtrampa para limpiar los archivos temporales creados durante la ejecución. La mayoría de los shells, incluidos bash, establecerán el estado del valor proporcionado en el exitcomando antes de llamar a la EXITtrampa. Eso podría permitir que la EXITtrampa detecte si se invocó por un error o por una terminación normal, y también le permite asegurarse de que el estado de salida esté configurado correctamente al final de la operación de captura.

Sin embargo, aparentemente algunos depósitos no cooperan. Aquí hay una cita del autoconfmanual :

Algunos scripts de shell, como los generados por autoconf, usan 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 decir que se produjo 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 exit directamente, use la AC_MSG_ERRORmacro que tiene una solución para este problema.

La solución es asegurarse de que $?tenga el estado de salida antes deexit ejecutar el comando, para que definitivamente tenga ese valor cuando EXITse ejecute la captura. Y, de hecho, es la AC_MSG_ERRORmacro la que inserta ese curioso código, completo con llaves redundantes.

rici
fuente
¿Por qué no simplemente ejecutar en falselugar de (exit 1)?
Ruslan
3
@Ruslan: Dos problemas. (1) Lo más importante: falseno le permite configurar el código de estado y no hay garantía en cuanto a qué estado distinto de cero devuelve. (2) falseno suele ser un componente incorporado, por lo que requiere un proceso secundario; en contraste, la mayoría de las conchas pueden evitar engendrar a un niño para que lo manipule (exit 1).
rici
8

Hasta donde puedo ver, no hay ningún propósito para esto, no hay nada que se pueda lograr directamente al iniciar una subshell y luego salir inmediatamente.

Es probable 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 la subshell donde tiene exit 1sentido. En última instancia, existe una buena posibilidad de que el código de generación se simplifique de alguna manera al permitirle insertar algunas declaraciones que no tienen ninguna función en algunos casos y generar '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 desee redirigir la salida / entrada del bloque) en lugar de distinguir el aquellos donde no son necesarios y omítalos.

Graeme
fuente
Tiene un propósito. Ver la respuesta de @ rici.
Old Pro
1

(exit 1)es una forma simple, probablemente la más simple de obtener un cierto código de salida (en el caso especial de 1 hay formas más fáciles, por supuesto). Pero esa no es la razón en este caso, ya que el código de salida no se examina.

El propósito de poner exituna subshell puede ser no salir de la secuencia de comandos (aunque use exit para generar un cierto código de salida).

Hauke ​​Laging
fuente