human
J'ai un script qui ne se termine pas quand je le souhaite.
Un script exemple avec la même erreur est le suivant:
```#!/bin/bash
function bla() {
    return 1
}
bla || ( echo '1' ; exit 1 )
echo '2'
```
Je m'attends à voir la sortie suivante:
```:~$ ./test.sh
1
:~$
```
Mais en réalité, je vois:
```:~$ ./test.sh
1
2
:~$
```
Est-ce que la chaîne de commandes ```()``` crée une portée d'une manière ou d'une autre ? À quoi ```exit``` met-il fin, si ce n'est pas le script
gpt
```()``` exécute les commandes dans le sous-shell, donc en utilisant ```exit```, vous quittez le sous-shell et revenez au shell parent. Utilisez les accolades ```{}``` si vous voulez exécuter les commandes dans le shell actuel.
D'après le manuel de bash :

  (liste) la liste est exécutée dans un environnement de sous-shell. Les affectations de variables et les commandes intégrées qui affectent l'environnement du shell ne restent pas en vigueur après l'exécution de la commande. Le statut de retour est le statut de sortie de la liste.
  { liste; } la liste est simplement exécutée dans l'environnement du shell actuel. La liste doit se terminer par un saut de ligne ou un point-virgule. Il s'agit d'une commande de groupe. Le statut de retour est le statut de sortie de la liste. Notez que contrairement aux méta-caractères ( et ), { et } sont des mots réservés et doivent apparaître là où un mot réservé est autorisé à être reconnu. Comme ils ne provoquent pas de rupture de mot, ils doivent être séparés de la liste par un espace ou un autre méta-caractère du shell.

Il convient de mentionner que la syntaxe du shell est assez cohérente et le sous-shell participe également aux autres constructions ```()``` comme la substitution de commandes (également avec l'ancienne syntaxe ````..````) ou la substitution de processus, donc les exemples suivants ne quittent pas non plus le shell actuel :
```echo $(exit)
cat <(exit)
```

Bien qu'il soit évident que des sous-shells sont impliqués lorsque des commandes sont placées explicitement à l'intérieur de ```()```, le fait moins visible est qu'ils sont également créés dans ces autres structures :

* commande démarrée en arrière-plan
```exit &
```
ne quitte pas le shell actuel car (d'après ```man bash```)

  Si une commande est terminée par l'opérateur de contrôle &, le shell exécute la commande en arrière-plan dans un sous-shell. Le shell n'attend pas que la commande se termine et le statut de retour est 0.

* le pipeline
```exit | echo foo
```
quitte toujours seulement le sous-shell.
Cependant, les différents shells se comportent différemment à cet égard. Par exemple, ```bash``` place tous les composants du pipeline dans des sous-shells distincts (sauf si vous utilisez l'option ```lastpipe``` dans les invocations où le contrôle des tâches n'est pas activé), mais ```ksh``` d'AT&T et ```zsh``` exécutent la dernière partie dans le shell actuel (les deux comportements sont autorisés par POSIX). Ainsi,
```exit | exit | exit
```
ne fait pratiquement rien dans bash, mais quitte le zsh en raison du dernier ```exit```.
* ```coproc exit``` exécute également ```exit``` dans un sous-shell.