Selon cela , placer une liste de commandes entre accolades entraîne l'exécution de la liste dans le contexte de shell actuel. Aucun sous-shell n'est créé .
Utiliser ps
pour voir cela en action
Il s'agit de la hiérarchie de processus pour un pipeline de processus exécuté directement sur la ligne de commande. 4398 est le PID du shell de connexion:
sleep 2 | ps -H;
PID TTY TIME CMD
4398 pts/23 00:00:00 bash
29696 pts/23 00:00:00 sleep
29697 pts/23 00:00:00 ps
Suit maintenant la hiérarchie des processus pour un pipeline de processus entre accolades exécutés directement sur la ligne de commande. 4398 est le PID du shell de connexion. Elle est similaire à la hiérarchie ci-dessus prouvant que tout est exécuté dans le contexte actuel du shell :
{ sleep 2 | ps -H; }
PID TTY TIME CMD
4398 pts/23 00:00:00 bash
29588 pts/23 00:00:00 sleep
29589 pts/23 00:00:00 ps
Maintenant, c'est la hiérarchie du processus lorsque le sleep
dans le pipeline est lui-même placé à l'intérieur des accolades (donc deux niveaux d'accolades en tout)
{ { sleep 2; } | ps -H; }
PID TTY TIME CMD
4398 pts/23 00:00:00 bash
29869 pts/23 00:00:00 bash
29871 pts/23 00:00:00 sleep
29870 pts/23 00:00:00 ps
Pourquoi faut bash
-il créer un sous-shell à exécuter sleep
dans le 3ème cas lorsque la documentation indique que les commandes entre accolades sont exécutées dans le contexte actuel du shell?
{ sleep 2 | command ps -H; }
Réponses:
Dans un pipeline, toutes les commandes s'exécutent simultanément (avec leur stdout / stdin connecté par des tuyaux) donc dans différents processus.
Dans
Les trois commandes s'exécutent dans des processus différents, donc au moins deux d'entre elles doivent s'exécuter dans un processus enfant. Certains shells exécutent l'un d'eux dans le processus de shell actuel (s'il est intégré
read
ou si le pipeline est la dernière commande du script), mais lesbash
exécute tous dans leur propre processus séparé (sauf avec l'lastpipe
option dans lesbash
versions récentes et dans certaines conditions spécifiques ).{...}
commandes de groupes. Si ce groupe fait partie d'un pipeline, il doit s'exécuter dans un processus distinct, tout comme une simple commande.Dans:
Nous avons besoin d'un shell pour évaluer qu'il
a; b "$?"
s'agit d'un processus distinct, nous avons donc besoin d'un sous-shell. Le shell pourrait optimiser en ne forkant pasb
car c'est la dernière commande à être exécutée dans ce groupe. Certains obus le font, mais apparemment pasbash
.la source
bash -c "sleep 112345 | cat | cat "
je ne vois qu'un seul bash créé et ensuite 3 enfants sans aucun autre sous-entrelacement entrelacé.a; b "$?"
? Existe-t-il vraiment un besoin fondamental pour une sous-roue, ou peut-être s'agit-il d'une décision de conception / mise en œuvre sur bash?eval
), mais l'évaluation (exécutez la première commande, attendez-la, exécutez la seconde) est fait chez l'enfant, celui qui a stdout connecté au tuyau.{ sleep 2 | ps -H; }
le bash parent voitsleep 2
que nécessite un fork / exec. Mais dans{ { sleep 2; } | ps -H; }
le bash parent voit{ sleep 2; }
en d'autres termes, du code bash. Il semble que le parent puisse gérer le fork / exec poursleep 2
mais génère un nouveau bash récursivement pour gérer le code bash rencontré. C'est ma compréhension, est-ce sensé?L'imbrication des accolades semble indiquer que vous créez un niveau supplémentaire de portée qui nécessite l'appel d'un nouveau sous-shell. Vous pouvez voir cet effet avec la 2ème copie de Bash dans votre
ps -H
sortie.Seuls les processus stipulés dans le premier niveau des accolades sont exécutés dans le cadre de la coque Bash d'origine. Toutes les accolades bouclées imbriquées s'exécuteront dans leur propre shell Bash de portée.
Exemple
En prenant le
| ps -H
mélange juste pour que nous puissions voir les accolades imbriquées, nous pouvons exécuterps auxf | less
dans un autre shell.Mais attendez, il y a plus!
Si vous retirez les tuyaux et utilisez cette forme de commande, nous voyons ce que vous attendez réellement:
Maintenant, dans la fenêtre de surveillance résultante, nous obtenons une mise à jour toutes les 2 secondes de ce qui se passe:
Voici le premier
sleep 10
:Voici la seconde
sleep 10
:Voici le troisième
sleep 10
:Notez que les trois dormeurs, bien qu'invoqués à différents niveaux d'imbrication des accolades, ne restent en fait pas dans le PID 5676 de Bash. Je crois donc que votre problème est auto-infligé avec l'utilisation de
| ps -H
.Conclusions
L'utilisation de
| ps -H
(c'est-à-dire le tube) provoque un sous-shell supplémentaire, alors n'utilisez pas cette méthode lorsque vous essayez d'interroger ce qui se passe.la source
Je posterai les résultats de mes tests, ce qui m'amène à conclure que bash crée un sous-shell pour une commande de groupe si et seulement si cela fait partie du pipeline, c'est comme si l'on appelait une fonction qui serait également appelée en sous-coque.
la source