¿Cuál es el propósito de la suspensión retardada (Ctrl-Y) en Bash?

30

La parte completa de la página de manual de Bash que es aplicable solo dice:

Si el sistema operativo en el que se ejecuta bash admite el control de trabajos, bash contiene funciones para usarlo. Al escribir el carácter de suspensión (generalmente ^ Z, Control-Z) mientras se está ejecutando un proceso, el proceso se detiene y el control vuelve a bash. Al escribir el carácter de suspensión retrasada (generalmente ^ Y, Control-Y), el proceso se detiene cuando intenta leer la entrada del terminal y el control vuelve a bash. El usuario puede manipular el estado de este trabajo, utilizando el bg comando para continuarlo en segundo plano, elfgcomando para continuar en primer plano, o el comando kill para matarlo. A ^ Z entra en vigencia inmediatamente y tiene el efecto secundario adicional de causar que se descarte la salida pendiente y la escritura anticipada.

Nunca he usado Ctrl- Y; Acabo de enterarme de eso. He hecho bien solo con Ctrl- Z(suspender).

Estoy tratando de imaginar lo que esta opción es para . ¿Cuándo sería útil?

(Tenga en cuenta que esta característica no existe en todas las variantes de Unix. Está presente en Solaris y FreeBSD pero no en Linux. La configuración correspondiente es stty dsusp).

Tal vez menos subjetivamente: ¿Hay algo que se puede lograr con Ctrl- Yque no se puede lograr con la misma facilidad con Ctrl- Z?

Comodín
fuente
@Gilles, aunque FreeBSD parece tener un stty dsusp, no he logrado que envíe un SIGTSTP a ^ Y (lo hice en Solaris). ¿Tienes?
Stéphane Chazelas

Respuestas:

23

Del manual de 4BSD para csh :

A ^Zsurte efecto de inmediato y es como una interrupción en que la salida pendiente y la entrada no leída se descartan cuando se escribe. Hay otra tecla especial ^Yque no genera una señal de PARADA hasta que un programa intenta leerla (2). Esto puede escribirse útilmente cuando haya preparado algunos comandos para un trabajo que desea detener después de leerlos.

Por lo tanto, el propósito es escribir múltiples entradas mientras se procesa la primera, y hacer que el trabajo se detenga después de que hayan terminado.

Aleatorio832
fuente
Esta descripción es sutilmente diferente del manual de bash. "... no genera una señal de DETENCIÓN hasta que un programa intente leerla " . Parece que todo en el flujo de entrada hasta la ^Ylectura se leerá con éxito, y luego, cuando ^Yse presione, el proceso se detendrá. ¿Estoy leyendo esto bien?
Comodín el
@Wildcard en mi prueba en Mac OS X, el proceso se detiene antes de que read () regrese (pero después de la llamada a read () que habría devuelto la Y), y después de que se reanuda, recibe la entrada de antes ^ Y . Sin embargo, creo que, como estaba destinado a ser utilizado, se usaría al comienzo de una línea, por lo que el comportamiento en este caso no importaría. Sospecho que en el código real, se suspende cuando ^ Y se habría copiado en el búfer de lectura del proceso del usuario.
Random832
Tenía razón, en la función ttread del núcleo BSD original se puede ver esto, y OSX moderno
Random832
Pero, cuando se reanuda el proceso, la llamada tendrá éxito y contendrá los datos que ingresó en su terminal antes ^Y, incluso si ha rechazado el proceso y cerrado su terminal antes de que se reanude el proceso. ¿Correcto? ( "... después de que se reanude que recibe la entrada de delante ^ Y." Eso es lo que quería decir, yo no suelen tratar en código C.) :)
Comodín
Sí. Y regresa sin una nueva línea al final, lo cual es inusual para una lectura en modo canónico [similar a si hubiera escrito algún texto y luego presionado ^ D una vez] Sospecho que no pensaron mucho en este caso, ya que Realmente está destinado a ser escrito al comienzo de una línea.
Random832
11

Digamos que hay un ciclo de lectura de entrada y ejecución. Puede ser útil dejar que la tarea finalice la instrucción actual que calcula, sin interrumpirla antes de que vuelva a la línea de comando para obtener una nueva. Entonces, para terminar un ciclo. Esto finaliza el bucle con gracia y evita que se ejecute nuevamente si readestá bajo una restricción de tiempo de espera.

Tomász
fuente
Pero si va a intentar leer la entrada del terminal de todos modos, se detendrá en ese punto (y esperará su entrada), y puede ^Zhacerlo entonces .
Comodín
Sí. Ver actualización.
Tomasz
Marque uno más. @Wildcard
Tomasz
1
Pero si tiene un tiempo de espera, ¿no terminaría también con gracia si no hiciera nada especial?
Daniel Wagner
1
Que podría. Pero también podría continuar y hacer un trabajo predeterminado.
Tomasz
4

Puedo pensar en un escenario en el que podría ser útil, pero es algo así como un caso extremo artificial.

Suponga que está depurando un script que está escribiendo archivos temporales que desea analizar antes de que se eliminen como parte de una rutina de limpieza.

Puede agregar un read fooarchivo en algún lugar después de escribir los archivos (pero antes de la limpieza), ejecutar el script y presionar Ctrl, a Ymedida que se generan. Luego, se lo dirigirá a un mensaje con el script suspendido en segundo plano para hacer lo que sea necesario y luego fgpodrá permitir que se complete el script.

DopeGhoti
fuente
1
Parece poco probable, porque el script esperará la entrada de todos modos. Por lo tanto, podría observarlo fácilmente para solicitarle información y luego suspenderlo ^Z. En otras palabras: después de escribir fg, tendrá que dar alguna entrada al script de todos modos antes de que continúe. De ahí mi pregunta; Todavía no veo el punto de ^Y. (¡Sin embargo, gracias por responder!) :)
Comodín
2

El único escenario en el que puedo pensar (e incluso no me parece muy convincente), es si desea utilizar algún tipo de escritura anticipada para un comando de shell. Digamos que se está ejecutando algún comando que leerá la entrada en algún momento en el futuro. Luego puede ^ Y, y luego escriba inmediatamente el siguiente comando de shell que desea ejecutar cuando se suspende el comando en ejecución. No creo haber usado esto realmente en varias décadas usando BSD Unix.

Olaf Seibert
fuente