2014-11-14 7 views
6

ctrl-z (^ z) verhält sich so, wie ich es nicht verstehe, wenn es innerhalb einer Schleife ausgeführt wird, die von einem Terminal ausgeführt wird.bg/fg in einer Befehlszeilenschleife

Say I

Typ
for ii in {0..100}; do echo $ii; sleep 1; done 

dann drücken I^Z. Ich werde erhalten:

Ich kann den Job mit fg oder bg fortsetzen, aber der Job bezieht sich nur auf den Schlafbefehl. Der Rest der Schleife ist anscheinend verschwunden, und auf dem Terminal erscheint keine Nummer mehr.

ich & nach dem Befehl verwenden könnte sofort im Hintergrund laufen zu lassen, oder ein andere Lösung ist das Ganze in einer Subshell zu wickeln:

(for ii in {0..100}; do echo $ii; sleep 1; done) 

dann^z gibt mir

[1]+ Stopped     (for ii in {0..100}; 
do 
    echo $ii; sleep 1; 
done) 

Dieser Job kann fortgesetzt werden und alle sind glücklich. Aber ich mache das normalerweise nicht, wenn ich eine einmalige Aufgabe erledige, und die Frage, die ich stelle, ist, warum das erste Verhalten überhaupt stattfindet. Gibt es eine Möglichkeit, eine Befehlszeilenschleife zu unterbrechen, die nicht subshell ist? Und was ist mit dem Rest der Schleife im ersten Beispiel passiert?

Beachten Sie, dass dies auf die Schleife spezifisch ist:

echo 1; sleep 5; echo 2 

und schlagen^z während des Schlafes bewirkt, dass die echo 2 auszuführen:

1 
^Z 
[2]+ Stopped     sleep 5 
2 

Oder sollte ich nur in die Gewohnheit, mit & und es dunkle Magie nennen?

Antwort

5

Sie können die Ausführung der aktuellen Shell nicht anhalten. Wenn Sie Ihre Schleife über die Befehlszeile ausführen, wird sie in Ihrer aktuellen Login-Shell/Terminal ausgeführt. Wenn Sie [ctrl + z] drücken, sagen Sie der Shell, dass sie den aktuellen aktiven Prozess anhalten soll. Ihre Schleife ist einfach ein Zähler in der aktuellen Shell, der ausgeführte Prozess ist sleep. Suspend funktioniert nur im Schlafmodus.

Wenn Sie einen Prozess starten oder ihn in einer Subshell (ungefähr gleichwertig) ausführen, können Sie diesen separaten Prozess insgesamt anhalten.

+1

Aber wenn Suspend nur auf diesen einzelnen Schlafbefehl funktioniert, warum nicht den Rest der Befehle ausführen (wie im Echo 1; Schlaf 5; Echo 2 Beispiel)? Ich würde in diesem Fall erwarten, dass der Schlaf aussetzt und der Rest der Schleife sofort fortgesetzt wird. Es scheint, dass^z nicht nur den Schlaf aufgehoben hat, sondern auch die Schleife beendet hat, und das verstehe ich nicht. –

+1

Ja, es tötet die Schleife. Sie haben Bash gesagt, dass er das aussetzen soll, was es tut. Der einzige Teil, den es aussetzen kann, ist der Schlaf. Der Rest geht weg. Ich werde nach einer Referenz für dich suchen. Lesen Sie 'man bash (JOB CONTROL)' Der Grund dafür ist, dass die Steuerung beim Aufruf von suspend zur Shell zurückkehren muss. Es gibt keine Möglichkeit, die aktuell ausgeführte Schleife beizubehalten, während die Steuerung an die Shell zurückgegeben wird, und da sie keine separate Pipeline hat, die angehalten werden kann, wird sie beendet, um die Steuerung an bash zurückzugeben. –