Problem
Ich führe Befehle aus, die VIELE Informationen über SSH ausgeben. Beispielsweise füge ich dummerweise Debuginformationen in eine Schleife ein, die millionenfach ausgeführt wird, oder führe sie einfach cat /dev/urandom
zum Spaß aus.
Das Terminal wird mit Informationen überflutet.
Ich möchte den Befehl so schnell wie möglich beenden und mein Programm reparieren. Es ist mir egal, was es ausgibt. Nun ist es so, dass ich Ctrl+ CASAP drücke (im obigen Beispiel habe ich es unmittelbar nach dem Ausführen des Befehls gedrückt), aberes dauert immer noch eine Weile, alle Informationen auszudrucken, die ich nicht einmal brauche.
Was ich versucht habe
Ich habe so fest versucht, Ctrl+ zu drücken C, dass es merkwürdige Ergebnisse gab, als das Terminal endlich nachkam:
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
Ich habe auch über Ctrl+ gelesen S, was anscheinendwird verwendet, um dem Terminal mitzuteilen: „Stopp die Ausgabe, ich muss aufholen“aber anscheinend tut es nichts.
Verschiedene Details
Ich möchte den von mir ausgeführten Befehl nicht ändern, damit ich mich in jeder Situation retten kann, auch wenn ich nicht daran denke, dass das von mir ausgeführte Programm so enden könnte.
Mein SSH-Client läuft auf Cygwin ( CYGWIN_NT-6.1-WOW64 luna 1.7.30(0.272/5/3) 2014-05-23 10:36 i686 Cygwin
) in MinTTY mit dem Terminaltyp auf eingestellt xterm-256color
.
Der SSH-Server läuft unter Debian ( Linux burza 3.2.0-4-686-pae #1 SMP Debian 3.2.51-1 i686 i686 i686 GNU/Linux
).
Antwort1
Normalerweise führe ich die Ausgabe in aus, less
damit ich sie über beenden kann, less
anstatt die qTaste zu verwenden.
$ cmd | less
Beispiel
$ cat /dev/urandom | less
Nach dem Drücken von q+ Enterwird es beendet und kehrt zu Ihrem normalen Terminal zurück, sodass es schön und sauber bleibt.
Warum passiert das?
Das Problem, auf das Sie stoßen, besteht darin, dass es Puffer (für STDOUT) gibt, die mit der Ausgabe Ihres Displays in die Warteschlange gestellt werden. Diese Puffer füllen sich so schnell, dass Sie sie nicht schnell genug unterbrechen können, um sie zu stoppen.
Um diesen Effekt zu deaktivieren/einzuschränken, können Sie die STDOUT-Pufferung deaktivieren, wodurch die Reaktionsfähigkeit etwas verbessert werden sollte stdbuf
, aber Sie müssen wahrscheinlich mit diesen Einstellungen herumspielen, um alles so zu bekommen, wie Sie es möchten. Um die Pufferung von STDOUT zu entfernen, können Sie diesen Befehl verwenden:
$ stdbuf -o0 <cmd>
Auf der Manpage finden Sie stdbuf
Einzelheiten zu den Ihnen zur Verfügung stehenden Optionen:
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.
Um einen guten Hintergrund zur Funktionsweise des Pufferns zu erhalten, empfehle ich Ihnen dringend, einen Blick auf diesen Artikel von Pixel Beat mit dem Titel zu werfen:Pufferung in Standard-Streams. Es enthält sogar schöne Bilder.
Verweise
Antwort2
Ein Teil dieser Ausgabe wird gepuffert. Sie senden Ihr Ctrl+ Can das Remote-Ende, wodurch das laufende Programm unterbrochen wird. Das Programm existiert und die Shell sendet die Zeichen, um Ihnen die Eingabeaufforderung erneut anzuzeigen. Bevor die Eingabeaufforderung angezeigt wird, zeigt Ihr Bildschirm zunächst alle Daten an, die gepuffert wurden und bereits auf dem Weg zu Ihnen sind.
Sie fordern, dass das Programm gestoppt wird und die übertragenen Daten irgendwie verschwinden. Das kann nicht passieren, da die Daten bereits unterwegs sind.
Die einzige Möglichkeit, um sicherzustellen, dass Sie diese Daten nicht sehen, besteht darin, das Terminal an Ihrem Ende zu beenden und dann erneut eine Verbindung zu Ihrem Remote-Computer herzustellen. Dies ist jedoch wahrscheinlich mit weitaus mehr Aufwand verbunden, als auf die Anzeige der gepufferten Daten zu warten.
Antwort3
Es gibt mehrere Pufferebenen. Wenn Sie Ctrl+ drücken C, wird das Programm daran gehindert, Daten an das Terminal auszugeben. Daten, die der Terminalemulator noch nicht angezeigt hat, sind hiervon nicht betroffen.
Wenn Sie Daten mit sehr hoher Geschwindigkeit anzeigen, kann das Terminal nicht mithalten und wird verzögert. Das ist es, was hier passiert: Das Anzeigen von Text ist viel teurer als das Erzeugen dieser Zufallszahlen. Ja, sogar mit einer Bitmap-Schriftart – das Erzeugen von Zufallszahlen in kryptografischer Qualität ist im Vergleich spottbillig. (Ich habe es gerade auf meinem Rechner versucht und der X-Prozess hat die CPU ausgelastet, wobei er xterm
ein paar Prozent einnahm und cat
(wobei die Zufallszahlengenerierung berücksichtigt wird) kaum 1 % erreichte. Und das mit einer Bitmap-Schriftart.)
Wenn Sie möchten, dass dies sofort beendet wird, beenden Sie den Terminalemulator. Wenn Sie das nicht möchten, minimieren Sie zumindest das Fenster. Intelligente Terminalemulatoren (wie xterm) werden das Fenster nicht abbilden, was der X-CPU-Zeit spart, sodass der Müll schneller angezeigt wird. Der X-Server hat hohe Priorität, daher wird dies einen großen Unterschied für die Reaktionsfähigkeit Ihres Computers bedeuten, während xterm die Daten im Hintergrund verarbeitet.
Wenn all dies in einer Remote-Shell geschieht, ist die Verzögerung noch schlimmer, da die von erzeugten Daten cat
zuerst über die SSH-Verbindung laufen müssen. Ihr Drücken von Ctrl+ Cmuss auch über die SSH-Verbindung laufen; es hat eine etwas höhere Priorität (es wird außerhalb des Bandes gesendet), aber das dauert trotzdem einige Zeit, während der sich mehr Ausgabe ansammelt. Es gibt keine Möglichkeit, Daten während der Übertragung zu unterdrücken, ohne die SSH-Verbindung zu schließen (was Sie tun können, indem Sie Enterdann drücken ~.
).
Antwort4
Ich hatte das gleiche Problem und war mit den Antworten hier nicht zufrieden, also habe ich tiefer gegraben. Andere haben bereits erwähnt, dass Ihr Befehl Daten schneller ausgibt, als Ihr SSH verarbeiten kann, sodass die Datenpuffer und Puffer nicht gestoppt werden können.
Um dies zu beheben, vermeiden Sie Pufferung, indem Sie Ihre Befehlsausgabe auf die maximale Rate drosseln, die Ihre SSH-Sitzung verarbeiten kann. Es gibt bereits Befehle, die dies tun.
Bei der Einrichtung ermitteln Sie zunächst die maximale Sitzungsrate:
# 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
Drosseln Sie abschließend Ihre tatsächlichen Befehle entsprechend.
<YOUR_COMMAND> | pv -qL <RATE>
Beispiel:
/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
Sie sollten die RATE ein wenig reduzieren, falls Ihre Verbindungsgeschwindigkeit von Zeit zu Zeit etwas abfällt. Wenn sie abfällt, tritt das Problem erneut auf, nämlich ein nicht reagierendes Strg-C.
Optionaler gedrosselter Cat-Alias:
# bash
alias tcat='tcat(){ cat $@ | pv -qL 400k ; }; tcat'
# tcsh
alias tcat 'cat \!* | pv -qL 400k'
# usage: tcat <FILENAME>
Jetzt funktioniert Strg-C wie erwartet und beendet die Ausgabe sofort, da nur sehr wenig oder gar nichts gepuffert wird.