Nach dieser , eine Liste von Befehlen zwischen geschweiften Klammern Platzieren bewirkt , dass die Liste in dem aktuellen Shell Kontext ausgeführt werden. Es wird keine Subshell erstellt .
Verwenden Sie ps
, um dies in Aktion zu sehen
Dies ist die Prozesshierarchie für eine Prozesspipeline, die direkt in der Befehlszeile ausgeführt wird. 4398 ist die PID für die Login-Shell:
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
Es folgt nun die Prozesshierarchie für eine Prozesspipeline zwischen geschweiften Klammern, die direkt in der Befehlszeile ausgeführt wird. 4398 ist die PID für die Login-Shell. Dies ähnelt der obigen Hierarchie, um zu beweisen, dass alles im aktuellen Shell-Kontext ausgeführt wird :
{ 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
Dies ist nun die Prozesshierarchie, wenn das sleep
in der Pipeline befindliche Element selbst in geschweiften Klammern steht (also insgesamt zwei Ebenen von Klammern).
{ { 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
Warum muss bash
eine Subshell erstellt werden, um sleep
im dritten Fall ausgeführt zu werden, wenn in der Dokumentation angegeben ist, dass Befehle zwischen geschweiften Klammern im aktuellen Shell-Kontext ausgeführt werden?
{ sleep 2 | command ps -H; }
Antworten:
In einer Pipeline werden alle Befehle gleichzeitig ausgeführt (wobei ihre stdout / stdin durch Pipes verbunden sind), also in unterschiedlichen Prozessen.
Im
Alle drei Befehle werden in unterschiedlichen Prozessen ausgeführt, sodass mindestens zwei von ihnen in einem untergeordneten Prozess ausgeführt werden müssen. Einige Shells führen eine von ihnen im aktuellen Shell-Prozess aus (wenn sie wie
read
die Pipeline erstellt wurden oder der letzte Befehl des Skripts ist), führenbash
sie jedoch alle in einem eigenen separaten Prozess aus (mit Ausnahme derlastpipe
Option in neuerenbash
Versionen und unter bestimmten Bedingungen) ).{...}
gruppen befehle. Wenn diese Gruppe Teil einer Pipeline ist, muss sie wie ein einfacher Befehl in einem separaten Prozess ausgeführt werden.Im:
Wir brauchen eine Shell, um zu bewerten, dass
a; b "$?"
es sich um einen separaten Prozess handelt, also brauchen wir eine Subshell. Die Shell kann optimiert werden, indem nicht nachgefragt wird,b
da dies der letzte Befehl ist, der in dieser Gruppe ausgeführt wird. Einige Muscheln tun es, aber anscheinend nichtbash
.quelle
bash -c "sleep 112345 | cat | cat "
sehe ich nur eine Bash erstellt und dann 3 Kinder dazu, ohne irgendwelche anderen verschachtelten Sub-Bashs.a; b "$?"
? Gibt es wirklich ein grundlegendes Bedürfnis nach einem Unterrad, oder handelt es sich möglicherweise um eine Entwurfsentscheidung / -implementierung auf Basis von Bash?eval
), aber die Auswertung (den ersten Befehl ausführen, darauf warten, den zweiten ausführen) getan in dem Kind, das stdout mit dem Rohr verbunden hat.{ sleep 2 | ps -H; }
der übergeordneten bash sieht mansleep 2
, dass ein fork / exec benötigt. Aber in{ { sleep 2; } | ps -H; }
der übergeordneten Bash sieht man{ sleep 2; }
mit anderen Worten Bash-Code. Es sieht so aus, als ob das übergeordnete Element die Abzweigung / Ausführung für verarbeiten kann,sleep 2
aber rekursiv eine neue Bash erzeugt, um den ermittelten Bash-Code zu verarbeiten. Das ist mein Verständnis, macht es Sinn?Das Verschachteln der geschweiften Klammern scheint darauf hinzudeuten, dass Sie eine zusätzliche Bereichsebene erstellen, die das Aufrufen einer neuen Sub-Shell erfordert. Sie können diesen Effekt mit der 2. Kopie von Bash in Ihrer
ps -H
Ausgabe sehen.Nur die in der ersten Ebene der geschweiften Klammern festgelegten Prozesse werden im Rahmen der ursprünglichen Bash-Shell ausgeführt. Alle geschachtelten geschweiften Klammern werden in ihrer eigenen Bash-Shell ausgeführt.
Beispiel
Wenn
| ps -H
wir die Mischung herausnehmen, damit wir die geschachtelten geschweiften Klammern sehen können, können wirps auxf | less
in einer anderen Shell laufen .Aber warte, es gibt noch mehr!
Wenn Sie jedoch die Rohre herausnehmen und diese Form eines Befehls verwenden, sehen wir, was Sie tatsächlich erwarten würden:
Jetzt erhalten wir im daraufhin angezeigten Überwachungsfenster alle 2 Sekunden eine Aktualisierung der aktuellen Ereignisse:
Hier ist der erste
sleep 10
:Hier ist der zweite
sleep 10
:Hier ist der dritte
sleep 10
:Beachten Sie, dass alle drei Schlafzustände, die bei verschiedenen Verschachtelungsstufen von geschweiften Klammern aufgerufen werden, tatsächlich innerhalb der PID 5676 von Bash bleiben. Ich glaube also, dass Ihr Problem durch die Verwendung von selbst verursacht wird
| ps -H
.Schlussfolgerungen
Die Verwendung von
| ps -H
(dh der Pipe) führt zu einer zusätzlichen Unterschale. Verwenden Sie diese Methode also nicht, wenn Sie versuchen, die aktuellen Ereignisse abzufragen.quelle
Ich werde Ergebnisse meiner Tests schreiben, die mich zu dem Schluss führt , dass bash eine Unterschale für eine Gruppe Befehl macht , wenn und nur wenn es ein Teil der Pipeline ist, die ähnlich ist , wie wenn man würde eine Funktion aufrufen , die auch genannt werden würde in Unterschale.
quelle