Was ist der Zweck der verzögerten Unterbrechung (Strg-Y) in Bash?

30

Der vollständige Teil der Bash-Manpage, der anwendbar ist, sagt nur:

Wenn das Betriebssystem, auf dem bash ausgeführt wird, die Jobsteuerung unterstützt, enthält bash Funktionen zur Verwendung. Wenn Sie das Suspend-Zeichen (normalerweise ^ Z, Strg-Z) eingeben, während ein Prozess ausgeführt wird, wird dieser Prozess angehalten und die Steuerung wird an die Bash zurückgegeben. Durch die Eingabe des verzögerten Anhaltezeichens (normalerweise ^ Y, Strg-Y) wird der Prozess angehalten, wenn versucht wird, Eingaben vom Terminal zu lesen, und die Steuerung wird an bash zurückgegeben. Der Benutzer kann dann den Status dieses Auftrags ändern, indem er den bg Befehl verwendet, um ihn im Hintergrund fortzusetzenfgBefehl, um es im Vordergrund fortzusetzen, oder Befehl kill, um es zu töten. A ^ Z wird sofort wirksam und hat den zusätzlichen Nebeneffekt, dass anstehende Ausgaben und Druckaufträge verworfen werden.

Ich habe noch nie benutzt Ctrl- Y; Ich habe es gerade erst gelernt. Ich habe es nur mit Ctrl- Z(suspend) gut gemacht.

Ich versuche mir vorzustellen , was diese Option ist für . Wann wäre es sinnvoll?

(Beachten Sie, dass diese Funktion nicht bei allen Unix-Varianten vorhanden ist. Sie ist unter Solaris und FreeBSD verfügbar, jedoch nicht unter Linux. Die entsprechende Einstellung lautet stty dsusp.)

Vielleicht weniger subjektiv: Gibt es etwas, mit dem man etwas erreichen kann Ctrl- Ydas man nicht so einfach erreichen kann Ctrl- Z?

Platzhalter
quelle
@ Gilles, obwohl FreeBSD ein zu haben scheint, habe stty dsuspich es nicht geschafft, ein SIGTSTP auf ^ Y zu senden (ich tat es auf Solaris). Hast du?
Stéphane Chazelas

Antworten:

23

Aus dem 4BSD-Handbuch für csh :

A ^Zwird sofort wirksam und ist wie ein Interrupt, bei dem anstehende und ungelesene Eingaben bei der Eingabe verworfen werden. Es gibt eine weitere Sondertaste, ^Ydie erst dann ein STOP-Signal erzeugt, wenn ein Programm versucht, es zu lesen (2). Dies kann nützlich sein, wenn Sie einige Befehle für einen Job vorbereitet haben, den Sie stoppen möchten, nachdem er sie gelesen hat.

Der Zweck besteht also darin, mehrere Eingaben einzugeben, während die erste verarbeitet wird, und den Job danach anzuhalten.

Random832
quelle
Diese Beschreibung unterscheidet sich geringfügig vom Bash-Handbuch. „... kein STOP - Signal erzeugen , bis ein Programm versucht , zu lesen es. Es klingt wie alles in dem Eingangsstrom auf bis den ^Yerfolgreich gelesen werden, und dann , wenn die ^Ygetroffen wird , wird der Prozess gestoppt werden. Lese ich das richtig?
Wildcard
@Wildcard In meinem Test unter Mac OS X wird der Prozess gestoppt, bevor read () zurückgegeben wird (aber nach dem Aufruf von read (), der das Y zurückgegeben hätte, wird ausgeführt), und nachdem er fortgesetzt wurde, erhält er die Eingabe von vor ^ Y . Ich denke, da dies verwendet werden sollte, würde es am Anfang einer Zeile verwendet werden, sodass das Verhalten in diesem Fall keine Rolle spielen würde. Ich vermute, dass es im eigentlichen Code angehalten wird, wenn das ^ Y in den Lesepuffer des Benutzerprozesses kopiert worden wäre.
Random832
Ich hatte recht, in der originalen ttread-Funktion des BSD-Kernels sieht man das und das moderne OSX
Random832
Wenn der Prozess fortgesetzt wird, ist der Anruf jedoch erfolgreich und enthält die Daten, die Sie zuvor in Ihr Terminal eingegeben haben ^Y, auch wenn Sie den Prozess abgelehnt und Ihr Terminal geschlossen haben, bevor der Prozess fortgesetzt wird. Recht? ( "... nachdem es wieder aufgenommen wurde, erhält es die Eingabe von vor ^ Y." Das habe ich gemeint; ich befasse mich normalerweise nicht mit C-Code.) :)
Wildcard
Ja. Und es wird am Ende ohne eine neue Zeile zurückgegeben, was für einen Lesevorgang im kanonischen Modus ungewöhnlich ist [ähnlich, wenn Sie einen Text eingegeben und dann ^ D einmal gedrückt haben]. Ich vermute, dass sie über diesen Fall nicht viel nachgedacht haben Es ist wirklich dazu gedacht, am Anfang einer Zeile getippt zu werden.
Random832
11

Angenommen, es wird eine Schleife zum Lesen eingegeben und ausgeführt. Es kann nützlich sein, die Aufgabe den aktuellen Befehl beenden zu lassen, ohne ihn zu unterbrechen, bevor sie für einen neuen Befehl zur Befehlszeile zurückkehrt. So also, um einen Zyklus zu beenden. Dies beendet die Schleife ordnungsgemäß und verhindert, dass sie erneut ausgeführt wird, wenn readeine Zeitüberschreitung vorliegt.

Tomasz
quelle
Aber wenn es trotzdem versucht, Eingaben vom Terminal zu lesen, stoppt es an diesem Punkt (und wartet auf Ihre Eingabe), und Sie können ^Zes dann tun .
Wildcard
Ja. Siehe update.
Tomasz
Überprüfen Sie noch einen. @Wildcard
Tomasz
1
Aber wenn es eine Auszeit gibt, würde es nicht auch elegant enden, wenn Sie nichts Besonderes getan haben?
Daniel Wagner
1
Es könnte. Es könnte aber auch so weitergehen und einen Standardjob erledigen.
Tomasz
4

Ich kann mir ein Szenario vorstellen, in dem es nützlich sein könnte, aber es ist so etwas wie ein erfundener Randfall.

Angenommen, Sie debuggen ein Skript, das temporäre Dateien schreibt, die Sie analysieren möchten, bevor sie im Rahmen einer Bereinigungsroutine gelöscht werden.

Sie können read fooirgendwo nach dem Schreiben der Dateien (aber vor der Bereinigung) ein hinzufügen , das Skript ausführen und Ctrl- drücken, Ywährend sie generiert werden. Sie werden dann zu einer Eingabeaufforderung weitergeleitet, in der das Skript im Hintergrund angehalten wird, um alle erforderlichen Aktionen auszuführen. Anschließend können Sie fgzulassen, dass das Skript ausgeführt wird.

DopeGhoti
quelle
1
Scheint unwahrscheinlich, da das Skript sowieso auf Eingaben wartet. Sie können also genauso gut darauf achten, dass Sie zur Eingabe aufgefordert werden, und es dann mit aussetzen ^Z. Mit anderen Worten: Nachdem Sie fgetwas eingegeben haben, müssen Sie dem Skript ohnehin eine Eingabe geben, bevor es fortgesetzt werden kann. Daher meine Frage; Ich verstehe immer noch nicht, worum es geht ^Y. (Danke für die Antwort!) :)
Wildcard
2

Das einzige Szenario, an das ich denken kann (und auch wenn ich es nicht sehr überzeugend finde), ist, wenn Sie einen Typ-Ahead-Befehl für ein Shell-Kommando verwenden möchten. Angenommen, ein Befehl wird ausgeführt, der zu einem späteren Zeitpunkt Eingaben lesen wird. Anschließend können Sie ^ Y it eingeben und sofort den nächsten Shell-Befehl eingeben, den Sie ausführen möchten, wenn der ausgeführte Befehl angehalten wird. Ich glaube nicht, dass ich dies in mehreren Jahrzehnten mit BSD Unix jemals wirklich genutzt habe.

Olaf Seibert
quelle