J'essaie d'écrire une fonction pour remplacer la fonctionnalité du exit
intégré pour m'empêcher de quitter le terminal.
J'ai essayé d'utiliser la variable d'environnement SHLVL
mais elle ne semble pas changer dans les sous-coquilles:
$ echo $SHLVL
1
$ ( echo $SHLVL )
1
$ bash -c 'echo $SHLVL'
2
Ma fonction est la suivante:
exit () {
if [[ $SHLVL -eq 1 ]]; then
printf '%s\n' "Nice try!" >&2
else
command exit
fi
}
Cela ne me permettra pas d'utiliser exit
dans les sous-coquilles:
$ exit
Nice try!
$ (exit)
Nice try!
Quelle est la bonne méthode pour détecter si je suis ou non dans un sous-shell?
En bash, vous pouvez comparer $BASHPID
à $$
$ ( if [ "$$" -eq "$BASHPID" ]; then echo not subshell; else echo subshell; fi )
subshell
$ if [ "$$" -eq "$BASHPID" ]; then echo not subshell; else echo subshell; fi
not subshell
Si vous n'êtes pas en bash, $$
devrait rester le même dans un sous-shell, vous auriez donc besoin d'une autre façon d'obtenir votre ID de processus réel.
Une façon d'obtenir votre pid réel est sh -c 'echo $PPID'
. Si vous venez de mettre cela dans un simple ( … )
il peut sembler que cela ne fonctionne pas, car votre Shell a optimisé la fourche. Essayez des commandes supplémentaires sans opération ( : ; sh -c 'echo $PPID'; : )
pour faire croire que le sous-shell est trop compliqué pour être optimisé. Le crédit revient à John1024 on Stack Overflow pour cette approche.
Que diriez-vous BASH_SUBSHELL
?
BASH_SUBSHELL
Incrémenté d'un dans chaque environnement de sous-shell ou sous-shell lorsque le shell
Commence à s'exécuter dans cet environnement. La valeur initiale est 0.
$ echo $BASH_SUBSHELL
0
$ (echo $BASH_SUBSHELL)
1
[cela aurait dû être un commentaire, mais mes commentaires ont tendance à être supprimés par les modérateurs, donc cela restera une réponse que je pourrais utiliser comme référence même s'il est supprimé]
En utilisant BASH_SUBSHELL
n'est absolument pas fiable car il n'est défini que sur 1 dans certains sous-coquilles, pas dans toutes les sous-coquilles.
$ (echo $BASH_SUBSHELL)
1
$ echo $BASH_SUBSHELL | cat
0
Avant de prétendre que le sous-processus dans lequel une commande de pipeline est exécutée n'est pas un véritable sous-shell réel, considérez ceci man bash
extrait:
Chaque commande d'un pipeline est exécutée en tant que processus distinct (c'est-à-dire dans un sous-shell).
et les implications pratiques - c'est si un fragment de script est exécuté sous-processus ou non, ce qui est essentiel, pas une petite gêne terminologique.
La seule solution, comme déjà expliqué dans les réponses à cette question est de vérifier si $BASHPID
équivaut à $$
ou, de manière portable mais beaucoup moins efficace:
if [ "$(exec sh -c 'echo "$PPID"')" != "$$" ]; then
echo you\'re in a subshell
fi