Detener la salida de un programa ejecutado en sesión SSH AHORA


18

Problema

Ejecuto un comando que genera MUCHA información a través de SSH. Por ejemplo, agrego tontamente información de depuración dentro de un bucle que se ejecuta millones de veces, o simplemente corro cat /dev/urandompor patadas.

La terminal está inundada de información.

Ejemplo de lo que estoy hablando

Quiero terminar el comando lo antes posible y arreglar mi programa. No me importa lo que imprima. Ahora, la cosa es que presiono Ctrl+ CASAP (en el ejemplo anterior lo presioné inmediatamente después de ejecutar el comando), pero aún así toma su tiempo imprimir toda la información que ni siquiera necesito .

Lo que he intentado

Intenté presionar Ctrl+ con Ctanta fuerza que tuvo resultados divertidos cuando la terminal finalmente se puso al día:

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í acerca de Ctrl+, Sque aparentemente se usa para decirle a la terminal "detener 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 establecido 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).


¿En qué sistema está ejecutando los programas reales que producen la salida? Linux, Unix o Windows? Linux y UNIX deberían aceptar Ctrl-O, lo que significa "descartar cualquier salida que se escriba en este terminal".
Mark Plotnick

El servidor se ejecuta en Debian. Editado la pregunta. Ctrl-O parece no hacer nada también. Tal vez es lo del cliente?
r-

Puede intentar iniciar su xterm con la -jopción, para habilitar el desplazamiento de salto. El problema básico es que el control remoto puede enviar datos más rápido de lo que la ventana del terminal puede mostrar; de manera predeterminada, tiene que bitblt el contenido de la ventana cada vez que se imprime una nueva línea. Una gran cantidad de datos pueden almacenarse en el momento en que su Ctrl-C sea recibido por el sistema remoto, y su programa de terminal intentará mostrarlos.
Mark Plotnick

Solo una idea: si tiene algunos comandos exactos que generalmente ejecuta accidentalmente y generan una gran cantidad de resultados, ¿por qué no simplemente agregar algunos alias .bashrc?
psimon

Puede usar mosh en lugar de ssh: mosh.mit.edu
gmatht el

Respuestas:


5

Parte de esa salida se almacenará temporalmente. Envía su Ctrl+ Cal extremo remoto que interrumpe el programa en ejecución. El programa existe y el shell envía los caracteres para mostrarte el aviso nuevamente. Antes de que se muestre el mensaje, su pantalla mostrará primero todos los datos almacenados en el búfer y que ya están en camino.

Lo que está pidiendo es que el programa se detenga y los datos en tránsito desaparezcan de alguna manera. Eso no puede suceder ya que está en camino.

La única forma en que puede asegurarse de no ver estos datos es salir de la terminal en su extremo y luego volver a conectarse a su control remoto, pero eso probablemente sea mucho más esfuerzo que esperar a que se muestren los datos almacenados.


10

Por lo general, ejecuto el resultado lesspara poder matarlo a través de lessla qtecla.

$ cmd | less

Ejemplo

$ cat /dev/urandom | less

   ss # 2

Después de presionar q+ Enterse cerrará y volverá a su terminal normal, dejándolo limpio y agradable.

¿Por qué pasa eso?

El problema con el que se encuentra es que hay buffers (para STDOUT) que se están poniendo en cola con la salida de su pantalla. Estas memorias intermedias se llenan tan rápido que no puede interrumpirlo lo suficientemente rápido como para detenerlo.

                                    ss # 1

Para deshabilitar / limitar este efecto, puede deshabilitar el almacenamiento intermedio STDOUT, lo que debería hacer que las cosas sean un poco más receptivas stdbuf, pero es probable que tenga que jugar con esta configuración para obtener las cosas de la manera que desee. Para quitar el buffer de STDOUT puedes usar este comando:

$ stdbuf -o0 <cmd>

La página de manual para stdbufdetalles de 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 un buen fondo sobre cómo funciona el almacenamiento en búfer, le recomiendo que eche un vistazo a este Pixel Beat articulado titulado: almacenamiento en búfer en secuencias estándar . Incluso incluye buenas fotos.

Referencias


Eso es razonable, siempre que se recuerde para anexar |lessa cmdque, lamentablemente, a menudo no lo hacen. Si ejecuta cmd, aún debe esperar hasta que termine de imprimir los resultados calculados antes de recibir ^C.
r-

1
Eso realmente no explica lo que está sucediendo. Después de todo, no hay tubería involucrada, entonces, ¿a qué búfer te refieres?
Gilles 'SO- deja de ser malvado'

@Gilles: lo siento, el búfer sería el búfer de la pantalla.
slm

¿Qué tampón? En el kernel? En xterm?
Gilles 'SO- deja de ser malvado'

@Gilles - dame un minuto, estoy buscando los detalles 8-)
slm

3

Hay varios niveles de almacenamiento en búfer. Cuando presiona Ctrl+ C, esto impide que el programa emita datos al terminal. Esto no afecta los datos que el emulador de terminal aún no ha mostrado.

Cuando se muestran datos a muy alta velocidad, el terminal no puede mantener el ritmo y se retrasará. Eso es lo que está sucediendo aquí: mostrar texto es mucho más costoso que producir estos números aleatorios. Sí, incluso con una fuente de mapa de bits: producir números aleatorios de calidad criptográfica es muy barato en comparación. (Acabo de probar en mi máquina y el proceso X saturó la CPU, con xtermun pequeño porcentaje y cat(que se tiene en cuenta en la generación de números aleatorios) apenas alcanza el 1%. Y eso con una fuente de mapa de bits).

Si quiere 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 asignarán la ventana, lo que ahorra el tiempo de CPU X, por lo que la basura terminará de mostrarse más rápido. El servidor X tiene alta prioridad, por lo que esto hará una gran diferencia en la capacidad de respuesta de su máquina mientras xterm procesa los datos en segundo plano.

Cuando todo esto ocurre en un shell remoto, el retraso es aún peor, porque los datos producidos por catprimero tienen que pasar por la conexión SSH. Su presió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 eso todavía lleva algún tiempo durante el cual se acumula más salida. No hay forma de suprimir los datos en tránsito antes de cerrar la conexión SSH (lo que puede hacer presionando Enterluego ~.).


El problema está relacionado con SSH. El buffer STDOUT no debe usarse en modo interactivo, pero SSH no puede manejar el modo interactivo correctamente. Aunque una gran cantidad de resultados puede bloquearse en la transacción, es el proceso SSH el que recibe Ctrl + C, por lo que es su responsabilidad matar el resultado cuando es imposible pasar Ctrl + C al control remoto.
user4674453

@ user4674453 ¿Uh? Se supone que Ctrl + C no mata la salida local. Ese no es su trabajo en absoluto. Se supone que debe pasar al lado remoto, lo que puede o no matar el proceso remoto.
Gilles 'SO- deja de ser malvado'

"Se supone que debe pasar al lado remoto, lo que puede o no matar el proceso remoto". - tampoco se supone que haga eso. Las señales KILL, Ctrl + C está emitiendo una de ellas, son solo para procesos locales. Si no se utiliza para el proceso local, la noción de "se supone que" no es aplicable en absoluto.
user4674453

@ user4674453 No. Ctrl + C no es una señal de muerte. Es una señal de interrupción. Su función es regresar a un mensaje interactivo. Solo mata los programas que no tienen un mensaje interactivo al que regresar.
Gilles 'SO- deja de ser malvado'

"Es una señal de interrupción". Es un argumento para matar el comando, por lo tanto, es una señal de matar. A veces se llama como señal POSIX si lo desea. "Su función es regresar a un mensaje interactivo. Solo mata los programas que no tienen un mensaje interactivo al que regresar". ¡¡¡Exactamente!!! Y SSH no hace eso como se esperaba.
user4674453

1

Debería ser suficiente para encontrar un camino hacia killel catcomando.
Para las siguientes propuestas, es posible que necesite una segunda conexión ssh abierta.

  • Raramente CTRL+zpuede ser más efectivo que CTRL+c: puede responder más rápido. Después de eso, suspende el comando con el que puede matarlo kill %1o lo que sea su número de trabajo.
    Esto con la esperanza de que aún pueda leer cualquier cosa de la pantalla (un texto binario aleatorio inundado puede arruinar fácilmente el conjunto de caracteres).
    Como recuerda Gilles, si minimiza la ventana, probablemente el sistema leerá la solicitud de interrupción más rápido que usted para eliminar el proceso. Así que suspender / romper, minimizar, esperar un poco, maximizar de nuevo, también puede ser una solución.
    Por supuesto, a través de una conexión ssh, espero que deba esperar un poco.

  • En otra terminal / sesión puede preguntar pgrep cat(si cat fue el comando invocado) e identificar que el proceso cat está usando más su CPU. Puede identificarlo con más precisión con pstree:

    gato pgrep | awk '{print "pstree -sp" $ 1}' | sh | grep sshd

    responder con una salida como

    init (1) ───sshd (1062) ───sshd (22884) ───sshd (22951) ───bash (22957) ───cat (23131)

    En este caso, después de que solo tengas que matar al PID del gato: kill 23131

Nota:


1

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 almacenamientos intermedios de datos y los almacenamientos intermedios no se pueden detener.

Para solucionar esto, evite el almacenamiento en búfer acelerando la salida de sus comandos a la velocidad máxima que su sesión ssh puede tomar, ya existen comandos para hacer esto.

Configuración, primero descubra la velocidad 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, estrangula 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 desee reducir la TASA un poco en caso de que la velocidad de su conexión disminuya un poco de vez en cuando. Si cae, el comportamiento volverá a emitirse, 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 se almacena muy poco, si es que hay alguno.


catLa salida rara vez es un problema, a diferencia de otro software. El autor solo lo usó como ejemplo. El problema generalmente se debe al otro software que puede no ser obvio si está dispuesto a producir muchos resultados. Usar cualquier tipo de comando prefijo o postfix no es una solución, ya que lleva tiempo escribirlo. No habrá ninguna ganancia en el resultado.
user4674453

0

Hay un software en Linux que resuelve exactamente este problema (algunas otras cosas también). También puede invocarlo desde un emulador de terminal en Windows (¿parece estar usando Windows?).

Prueba mosh , un reemplazo para el binario SSH. Funciona exactamente como SSH (puede hacerlo en mosh user@hostnamelugar de ssh user@hostnamey funcionaría exactamente como esperaba, incluso hará la autenticación de clave privada, etc.

Básicamente ejecuta un proceso separado en el servidor que almacena los paquetes. Entonces, cuando presiona Ctrl + C en mosh, lo transmitirá al servidor remoto, que luego dejará de enviar la información adicional. Además, también predecirá el resultado de las pulsaciones de teclas, lo que le ahorrará un par de milisegundos cada vez que presione una tecla.

Desventaja: actualmente no es posible desplazarse hacia arriba en la historia mientras se usa mosh.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.