Problema
Ejecuto un comando que genera MUCHA información a través de SSH. Por ejemplo, tontamente agrego información de depuración dentro de un bucle que se ejecuta millones de veces, o simplemente lo ejecuto cat /dev/urandom
por diversión.
La terminal está inundada de información.
Quiero finalizar el comando lo antes posible y arreglar mi programa. No me importa lo que imprima. Ahora, la cosa es que presiono Ctrl+ Clo antes posible (en el ejemplo anterior lo presioné inmediatamente después de ejecutar el comando), peroTodavía me toma tiempo imprimir toda la información que ni siquiera necesito..
lo que he probado
Intenté presionar Ctrl+ Ccon tanta fuerza que obtuve resultados divertidos cuando la terminal finalmente lo alcanzó:
OUTPUT HERE^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
^C^C
^C^C^C^C^C^C^C^C^C^C^C
^C^C^C^C^C^C^C^C^C^C
^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C
^C^C^C^C^C^C^C
^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C
^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C
^C^C^C^C^C^C^C^C^C^C^C^C^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
rr-@burza:~/xor$ ^C
También leí sobre Ctrl+ Sque aparentementese usa para decirle al terminal "detener la salida, necesito ponerme al día"pero aparentemente no hace nada.
Detalles varios
Me gustaría no alterar el comando que ejecuto para poder rescatarme en cualquier situación, incluso si no recuerdo que el programa que ejecuto podría terminar así.
Mi cliente SSH se ejecuta en Cygwin ( CYGWIN_NT-6.1-WOW64 luna 1.7.30(0.272/5/3) 2014-05-23 10:36 i686 Cygwin
) en MinTTY con el tipo de terminal configurado en xterm-256color
.
El servidor SSH se ejecuta en Debian ( Linux burza 3.2.0-4-686-pae #1 SMP Debian 3.2.51-1 i686 i686 i686 GNU/Linux
).
Respuesta1
Por lo general, ejecuto la salida less
para poder eliminarla less
usando la qclave.
$ cmd | less
Ejemplo
$ cat /dev/urandom | less
Después de presionar q+, Enterse cerrará y regresará a su terminal normal, dejándolo limpio y agradable.
¿Por qué sucede eso?
El problema que está encontrando es que hay buffers (para STDOUT) que están en cola con la salida de su pantalla. Estos buffers se llenan tan rápido que no puedes interrumpirlos lo suficientemente rápido como para detenerlos.
Para deshabilitar/limitar este efecto, puedes deshabilitar el almacenamiento en búfer STDOUT, lo que debería hacer que las cosas respondan un poco más usando stdbuf
, pero probablemente tendrás que jugar con estas configuraciones para obtener las cosas como deseas. Para eliminar el buffer STDOUT puedes usar este comando:
$ stdbuf -o0 <cmd>
La página de manual para stdbuf
detallar las opciones a su disposición:
If MODE is 'L' the corresponding stream will be line buffered. This
option is invalid with standard input.
If MODE is '0' the corresponding stream will be unbuffered.
Otherwise MODE is a number which may be followed by one of the
following: KB 1000, K 1024, MB 1000*1000, M 1024*1024, and so
on for G, T, P, E, Z, Y. In this case the corresponding stream will be
fully buffered with the buffer size set to MODE
bytes.
Para obtener información general sobre cómo funciona el almacenamiento en búfer, le sugiero que lea este artículo de Pixel Beat titulado:almacenamiento en búfer en transmisiones estándar. Incluso incluye bonitas fotografías.
Referencias
Respuesta2
Parte de esa salida se almacenará en búfer. Envía su Ctrl+ Cal extremo remoto, lo que interrumpe el programa en ejecución. El programa existe y el shell envía los caracteres para mostrarle el mensaje nuevamente. Antes de que se muestre el mensaje, su pantalla primero mostrará todos los datos que se almacenaron en el búfer y que ya están en camino hacia usted.
Lo que estás pidiendo es que el programa se detenga y que los datos en tránsito desaparezcan de alguna manera. Eso no puede suceder porque ya está en camino.
La única manera de asegurarse de no ver estos datos es salir del terminal en su extremo y luego volver a conectarse a su control remoto, pero eso probablemente represente mucho más esfuerzo que esperar a que se muestren los datos almacenados en el buffer.
Respuesta3
Hay varios niveles de almacenamiento en búfer. Cuando presionas Ctrl+ C, esto detiene el programa de emitir datos al terminal. Esto no afecta los datos que el emulador de terminal aún no ha mostrado.
Cuando muestra datos a muy alta velocidad, el terminal no puede seguir el ritmo y se retrasa. Eso es lo que está pasando aquí: mostrar texto es mucho más caro que producir estos números aleatorios. Sí, incluso con una fuente de mapa de bits: producir números aleatorios con calidad criptográfica es muy barato en comparación. (Acabo de probarlo en mi máquina y el proceso X saturó la CPU, tomando xterm
unos pocos % y cat
(con lo que se tiene en cuenta la generación de números aleatorios) apenas alcanzando el 1%. Y eso es con una fuente de mapa de bits).
Si desea que esto se detenga ahora, elimine el emulador de terminal. Si no desea hacer eso, al menos minimice la ventana; Los emuladores de terminal inteligentes (como xterm) no mapearán la ventana, lo que ahorra tiempo a la CPU X, por lo que la basura terminará de mostrarse más rápido. El servidor X tiene alta prioridad, por lo que esto marcará una gran diferencia en la capacidad de respuesta de su máquina mientras xterm procesa los datos en segundo plano.
Cuando todo esto sucede en un shell remoto, el retraso es aún peor, porque los datos producidos cat
primero tienen que pasar por la conexión SSH. Su pulsación de Ctrl+ Ctambién tiene que pasar por la conexión SSH; obtiene una prioridad algo mayor (se envía fuera de banda), pero aún lleva algún tiempo durante el cual se acumula más salida. No hay forma de suprimir los datos en tránsito salvo cerrar la conexión SSH (lo que puede hacer presionando Enterluego ~.
).
Respuesta4
Tuve el mismo problema y no estaba satisfecho con las respuestas aquí, así que profundicé. Otros ya han mencionado que su comando está generando datos más rápido de lo que su ssh puede tomar, por lo que los buffers de datos y los buffers no se pueden detener.
Para solucionar este problema, evite el almacenamiento en búfer limitando la salida de su comando a la velocidad máxima que su sesión ssh puede tomar; ya existen comandos para hacer esto.
Configuración, primero averigüe la tarifa máxima de sus sesiones:
# Get transfer <TIME> of a large file (>10MB preferable)
/usr/bin/time -f "%e" cat <FILENAME>
# Get file <SIZE> in bytes
stat --printf="%s\n" <FILENAME>
# Calculate <RATE>
echo "<SIZE> / <TIME>" | bc
Finalmente, acelera tus comandos reales en consecuencia.
<YOUR_COMMAND> | pv -qL <RATE>
Ejemplo:
/usr/bin/time -f "%e" cat large_reference_file.txt
31.26
stat --printf="%s\n" cat large_reference_file.txt
17302734
echo "17302734 / 31.26" | bc
553510
# Throttle my command to 553510B/s
cat some_other_file.txt | pv -qL 553510
Es posible que desees reducir un poco la TARIFA en caso de que la velocidad de tu conexión baje un poco de vez en cuando. Si baja, el comportamiento volverá al problema, un Ctrl-c que no responde.
Alias de gato estrangulado opcional:
# bash
alias tcat='tcat(){ cat $@ | pv -qL 400k ; }; tcat'
# tcsh
alias tcat 'cat \!* | pv -qL 400k'
# usage: tcat <FILENAME>
Ahora Ctrl-c funciona como se esperaba, eliminando inmediatamente la salida, ya que hay muy poco o nada almacenado en el buffer.