Que signifie `{{(exit 1); sortie 1; }; } `signifie?


28

J'ai cité l'extrait de code suivant config.statusgénéré par 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

Dans l'extrait de code, que fait { (exit 1); exit 1; };-on? Quel est le but de faire uniquement exitdans un sous-shell?

Réponses:


33

L'exécution (exit 1);est le moyen le plus simple de déclencher une ERRinterruption. Il déclenchera également une sortie immédiate s'il set -eest en vigueur. (Le déclenchement de la condition d'erreur nécessite l'échec d'une commande; exitune valeur d'échec dans un sous-shell entraîne l'échec du sous-shell.)

exit 1; ne fera rien de ces choses.

Donc, {(exit 1); exit 1;}peut être utilisé pour produire d'abord le ERRpiège, ce qui pourrait faire quelque chose d'utile à des fins de débogage, puis terminer le script avec une indication d'erreur.

Mais ce n'est pas ce qui se passe dans les autoconffichiers. autoconfles scripts s'appuient sur le EXITpiège pour nettoyer les fichiers temporaires créés pendant l'exécution. La plupart des shells, y compris bash, définiront l'état à partir de la valeur fournie dans la exitcommande avant d'appeler l' EXITinterruption. Cela pourrait permettre à l' EXITinterruption de détecter si elle a été invoquée à partir d'une erreur ou d'une terminaison normale, et cela lui permet également de s'assurer que l'état de sortie est correctement défini à la fin de l'opération d'interruption.

Cependant, apparemment, certains obus ne coopèrent pas. Voici une citation du autoconfmanuel :

Certains scripts shell, tels que ceux générés par autoconf, utilisent un piège pour nettoyer avant de quitter. Si la dernière commande shell s'est terminée avec un état différent de zéro, l'interruption se termine également avec un état différent de zéro afin que l'appelant puisse dire qu'une erreur s'est produite.

Malheureusement, dans certains shells, tels que Solaris /bin/sh, un piège de sortie ignore l'argument de la commande exit. Dans ces shells, une interruption ne peut pas déterminer si elle a été invoquée par une sortie standard ou par la sortie 1. Au lieu d'appeler directement la sortie, utilisez la AC_MSG_ERRORmacro qui a une solution de contournement pour ce problème.

La solution de contournement consiste à s'assurer qu'il $?a le statut de sortie avant l' exitexécution de la commande, afin qu'il ait définitivement cette valeur lors de l' EXITexécution de l'interruption. Et, en effet, c'est la AC_MSG_ERRORmacro qui insère ce code curieux, complet avec des accolades redondantes.


Pourquoi ne pas simplement exécuter falseau lieu de (exit 1)?
Ruslan

3
@Ruslan: Deux problèmes. (1) Plus important: falsene vous permet pas de définir le code d'état et il n'y a aucune garantie quant à l'état non nul qu'il renvoie. (2) falsen'est généralement pas intégré, il nécessite donc un processus enfant; en revanche, la plupart des coquilles peuvent éviter de donner naissance à un enfant à manipuler (exit 1).
rici

8

Pour autant que je sache, il n'y a aucun but, il n'y a rien qui puisse être réalisé directement en démarrant un sous-shell puis en quittant immédiatement.

Des choses comme celle-ci sont très probablement un effet secondaire de la génération automatique de code - dans certains cas, il peut y avoir d'autres commandes exécutées dans le sous-shell où avoir le exit 1 sens. En fin de compte, il y a de fortes chances que le code de génération soit en quelque sorte simplifié en lui permettant d'insérer des instructions qui n'ont aucune fonction dans certains cas plutôt et en générant du `` code propre '' à chaque fois est plus complexe. Soit cela, soit le code qui a généré ce qui précède est mal écrit :)

L'utilisation libérale de {...}est un autre exemple de cela, la plupart d'entre eux sont redondants, mais il est plus facile d'écrire du code qui les insère dans tous les cas (peut-être dans certains, vous voulez rediriger la sortie / entrée du bloc) plutôt que de distinguer le ceux où ils ne sont pas nécessaires et les omettre.


Cela a un but. Voir la réponse de @ rici.
Old Pro

1

(exit 1)est un moyen simple, probablement le plus simple d'obtenir un certain code de sortie (dans le cas spécial de 1, il existe des moyens plus faciles, bien sûr). Mais ce n'est pas la raison dans ce cas car le code de sortie n'est pas examiné.

Le but de mettre exitun sous-shell peut être de ne pas quitter le script (bien qu'en utilisant exit pour la génération d'un certain code de sortie).

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.