J'essaie d'écrire une fonction pour remplacer la fonctionnalité du exit
builtin pour m'empêcher de quitter le terminal.
J'ai essayé d'utiliser la SHLVL
variable d'environnement 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 cependant:
$ exit
Nice try!
$ (exit)
Nice try!
Quelle est la bonne méthode pour détecter si je suis ou non dans un sous-shell?
(...)
héritent de toutes les propriétés du processus parent. Les réponses fournies sont des solutions plus robustes pour déterminer votre niveau de shell.BASH_SUBSHELL
réponse (même controversée) ne s'appliquerait pas à cette question.Réponses:
En bash, vous pouvez comparer
$BASHPID
à$$
Si vous n'êtes pas dans 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 en clair,( … )
cela peut sembler ne pas fonctionner, car votre coque a optimisé la fourche. Essayez des commandes supplémentaires sans opération( : ; sh -c 'echo $PPID'; : )
pour lui faire croire que le sous-shell est trop compliqué pour être optimisé. Le crédit va à John1024 sur Stack Overflow pour cette approche.la source
(sh -c 'echo $PPID'; : )
- voir mon commentaire sur la réponse de John1024 .Et alors
BASH_SUBSHELL
?la source
[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é]
L'utilisation
BASH_SUBSHELL
est complètement peu fiable car elle n'est définie que sur 1 dans certains sous-coquilles, pas dans toutes les sous-coquilles.Avant de prétendre que le sous-processus dans lequel une commande de pipeline est exécutée n'est pas un sous-shell vraiment réel, considérez cet
man bash
extrait:et les implications pratiques - c'est si un fragment de script est exécuté ou non sous-processus qui est essentiel, pas un petit problème de terminologie.
La seule solution, comme déjà expliqué dans les réponses à cette question, est de vérifier si
$BASHPID
égal$$
ou, de manière portative mais beaucoup moins efficace:la source
BASH_SUBSHELL
est défini de manière assez fiable, mais obtenir sa valeur correctement est incertain. Notez ce que les documents disent: "Incrémenté d'un dans chaque environnement de sous-shell ou de sous-shell lorsque le shell commence à s'exécuter dans cet environnement. " Je pense que dans l'exemple de canal, bash n'a pas encore commencé à s'exécuter dans ce sous-shell lorsque la variable est développée. Vous pouvez comparerecho $BASH_VERSION
avecdeclare -p BASH_VERSION
- ce dernier devrait afficher de manière fiable 1 avec des tuyaux, des travaux d'arrière-plan, etc.eval 'echo $BASH_SUBSHELL $BASHPID' | cat
affichera 1 pourBASH_SUBSHELL
, car la variable est développée après le démarrage de l'exécution.subshell_level
est vraiment différée dans le cas des pipelines de premier plan , ce qui a probablement une raison, mais que je ne peux pas distinguer ;-)echo $$ $BASHPID $BASH_SUBSHELL | cat
.