À quoi sert la suspension différée (Ctrl-Y) dans Bash?

30

La partie complète de la page de manuel de Bash qui s'applique s'applique uniquement:

Si le système d'exploitation sur lequel bash s'exécute prend en charge le contrôle des travaux, bash contient des fonctionnalités pour l'utiliser. La saisie du caractère de suspension (généralement ^ Z, Control-Z) pendant l'exécution d'un processus entraîne l'arrêt de ce processus et renvoie le contrôle à bash. La saisie du caractère de suspension différée (généralement ^ Y, Control-Y) entraîne l'arrêt du processus lorsqu'il tente de lire l'entrée du terminal et le retour du contrôle à bash. L'utilisateur peut alors manipuler l'état de ce travail, en utilisant la bg commande pour le continuer en arrière-plan, lefgpour continuer au premier plan, ou la commande kill pour le tuer. A ^ Z prend effet immédiatement et a pour effet secondaire supplémentaire de supprimer la sortie et la frappe en attente.

Je n'ai jamais utilisé Ctrl- Y; Je viens juste de l'apprendre. J'ai bien fait avec Ctrl- Z(suspendre) seulement.

Je suis en train d'imaginer ce que cette option est pour . Quand serait-ce utile?

(Notez que cette fonctionnalité n'existe pas sur toutes les variantes Unix. Elle est présente sur Solaris et FreeBSD mais pas sur Linux. Le paramètre correspondant est stty dsusp.)

Peut-être moins subjectivement: y a-t-il quelque chose qui peut être accompli avec Ctrl- Yqui ne peut pas être accompli aussi facilement avec Ctrl- Z?

Wildcard
la source
@ Gilles, bien que FreeBSD semble en avoir un stty dsusp, je n'ai pas réussi à lui faire envoyer un SIGTSTP sur ^ Y (je l'ai fait sur Solaris). Avez-vous?
Stéphane Chazelas

Réponses:

23

Du manuel 4BSD pour csh :

A ^Zprend effet immédiatement et est comme une interruption dans la mesure où la sortie en attente et l'entrée non lue sont ignorées lors de la frappe. Il existe une autre touche spéciale ^Yqui ne génère pas de signal STOP jusqu'à ce qu'un programme tente de le lire (2). Cela peut être utilement tapé à l'avance lorsque vous avez préparé certaines commandes pour un travail que vous souhaitez arrêter après les avoir lues.

Ainsi, le but est de taper plusieurs entrées pendant que la première est en cours de traitement et d'arrêter le travail une fois qu'elles sont terminées.

Au hasard832
la source
Cette description est subtilement différente du manuel bash. « ... ne génère pas un signal d'arrêt jusqu'à une tentative de programme pour lire ce. » On dirait que tout dans le flux d' entrée jusqu'à l' ^Ysera lu avec succès, puis lorsque le ^Yest frappé le processus sera arrêté. Suis-je en train de lire ça?
Wildcard du
@Wildcard dans mon test sur Mac OS X, le processus est arrêté avant le retour de read () (mais après l'appel à read () qui aurait renvoyé les exécutions Y), et après sa reprise, il reçoit l'entrée d'avant ^ Y . Je pense que comme cela était destiné à être utilisé, cependant, il serait utilisé au début d'une ligne, donc le comportement dans ce cas n'aurait pas d'importance. Je soupçonne que dans le code réel, il est suspendu lorsque le ^ Y aurait été copié dans le tampon de lecture du processus utilisateur.
Random832
J'avais raison, dans la fonction ttread du noyau BSD d'origine, vous pouvez voir cela, et OSX moderne
Random832
Mais, lorsque le processus reprendra, l'appel réussira et contiendra les données que vous avez tapées dans votre terminal auparavant ^Y, même si vous avez renié le processus et fermé votre terminal avant la reprise du processus. Droite? ( "... après sa reprise, il reçoit l'entrée d'avant ^ Y." C'est ce que je voulais dire; je ne traite généralement pas en code C.) :)
Wildcard
Oui. Et il revient sans une nouvelle ligne à la fin, ce qui est inhabituel pour une lecture en mode canonique [similaire à si vous aviez tapé du texte puis appuyé une fois sur ^ D] Je soupçonne qu'ils n'ont pas beaucoup pensé à ce cas, car il est vraiment destiné à être tapé au début d'une ligne.
Random832
11

Disons qu'il y a une entrée de lecture en boucle et une exécution. Il peut être utile de laisser la tâche terminer l'instruction en cours qu'elle calcule, sans l'interrompre avant de revenir à la ligne de commande pour une nouvelle. Donc donc pour terminer un cycle. Cela termine la boucle gracieusement et l'empêche de s'exécuter à nouveau s'il readest soumis à une restriction de délai d'attente.

Tomasz
la source
Mais s'il essaie quand même de lire l'entrée du terminal, il s'arrêtera à ce point (et attendra votre entrée), et vous pourrez le ^Zfaire ensuite .
Wildcard
Oui. Voir mise à jour.
Tomasz
Vérifiez-en un de plus. @Wildcard
Tomasz
1
Mais s'il a un temps mort, ne se terminera-t-il pas simplement si vous n'avez rien de spécial?
Daniel Wagner
1
C'est possible. Mais il pourrait également continuer et faire un travail par défaut.
Tomasz
4

Je peux penser à un scénario où cela pourrait être utile, mais c'est quelque chose d'un cas de bord artificiel.

Supposons que vous déboguez un script qui écrit des fichiers temporaires que vous souhaitez analyser avant de les supprimer dans le cadre d'une routine de nettoyage.

Vous pouvez ajouter un read fooquelque part après l'écriture des fichiers (mais avant le nettoyage), exécuter le script et appuyer sur Ctrl- au Yfur et à mesure qu'ils sont générés. Vous serez ensuite redirigé vers une invite avec le script suspendu en arrière-plan pour faire tout ce que vous devez faire, et pourrez ensuite fgautoriser le script à se terminer.

DopeGhoti
la source
1
Cela semble peu probable, car le script attendra quand même la saisie. Vous pouvez donc tout aussi facilement le surveiller pour vous inviter à entrer, puis le suspendre avec ^Z. En d' autres termes: une fois que vous tapez , fgvous devrez donner une entrée le script de toute façon avant qu'il continuera. D'où ma question; Je ne vois toujours pas l'intérêt de ^Y. (Merci d'avoir répondu, cependant!) :)
Wildcard
2

Le seul scénario auquel je peux penser (et même je ne le trouve pas très convaincant), c'est si vous voulez utiliser un type-ahead pour une commande shell. Dites qu'une commande est en cours d'exécution et qu'elle lira les entrées dans le futur. Ensuite, vous pouvez le faire ^ Y, puis taper immédiatement la commande shell suivante que vous souhaitez exécuter lorsque la commande en cours se suspend. Je ne pense pas avoir vraiment utilisé cela depuis plusieurs décennies d'utilisation de BSD Unix.

Olaf Seibert
la source