Shell zeigt keine eingegebenen Befehle an, "reset" funktioniert, aber was ist passiert?

57

Mein Problem ist, dass die Bash-Shell nicht mehr die Zeichen anzeigt, die ich eingebe. Es liest jedoch die Befehle.

Ich bin schon einige Male auf dieses Problem gestoßen und verstehe nicht, woran es liegt. Ich weiß, wie man es löst, aber ich mag es wirklich nicht, wenn ich meine Art, Probleme zu lösen, "voodoo".

Ich beschreibe die beiden Möglichkeiten, auf die ich dieses Problem gestoßen bin:

Ich führe einen bestimmten Prozess aus, http://pythonpaste.org/script/, und manchmal, wenn ich damit aufhöre oder es die Kontrolle bricht, wird die Shell zurückgegeben. Wenn ich dann Befehle in die Shell eingebe, werden die eingegebenen Zeichen nicht angezeigt. Wenn ich die Befehle Eingabetaste drücken werden vorgelegt. Also zum Beispiel:

  • Ich tippe "ls"
  • Ich sehe nur eine leere Eingabeaufforderung und nichts mehr
  • Ich drücke die Eingabetaste und bekomme eine Liste der Dateien, mit anderen Worten: Der Befehl wird ausgeführt
  • Wenn ich den Befehl "reset" gebe, funktioniert die Shell wieder normal

Der zweite Weg ist, wenn ich einen Befehl wie diesen gebe:

$ grep foo * -l | xargs vim

Ich benutze grep, um Dateien mit einem bestimmten Muster zu finden, und möchte dann alle Dateien öffnen, die sich aus grep ergeben. Dies funktioniert wie ein Zauber (obwohl nicht so schnell wie ich gehofft hatte). Aber wenn ich Vim verlasse, zeigt meine Shell nicht mehr die Zeichen an, die ich eingebe. Ein Reset-Befehl behebt das Problem.

Meine Vermutung ist, dass beide Probleme einen Grund haben, aber ich bin irgendwie ratlos darüber, wie oder was dieser Grund ist.

Die Suche nach diesem Problem ist an sich problematisch, da die Beschreibung etwas vage ist und keine harten Suchbegriffe enthält.

Bearbeiten

Geben die

stty --all

Befehl gemäß der Anfrage von John S. Gruber gab die folgende Ausgabe aus (Leerzeichen zur besseren Lesbarkeit bearbeitet)

speed 0 baud;
rows 53;
columns 186;
line = 0;
intr = <undef>;
quit = <undef>;
erase = <undef>;
kill = <undef>; 
eof = <undef>;
eol = <undef>; 
eol2 = <undef>; 
swtch = <undef>; 
start = <undef>; 
stop = <undef>; 
susp = <undef>;
rprnt = <undef>; 
werase = <undef>; 
lnext = <undef>; 
flush = <undef>; 
min = 0; 
time = 0;
-parenb 
-parodd cs8 
-hupcl 
-cstopb cread 
-clocal 
-crtscts
-ignbrk 
-brkint 
-ignpar 
-parmrk 
-inpck 
-istrip 
-inlcr 
-igncr 
-icrnl 
-ixon 
-ixoff 
-iuclc 
-ixany 
-imaxbel 
-iutf8
-opost 
-olcuc 
-ocrnl 
-onlcr 
-onocr 
-onlret 
-ofill 
-ofdel nl0 cr0 tab0 bs0 vt0 ff0
-isig 
-icanon 
-iexten 
-echo 
-echoe 
-echok 
-echonl 
-noflsh 
-xcase 
-tostop 
-echoprt 
-echoctl 
-echoke
Niels Bom
quelle
2
In diesem Fall geben Sie bitte stty --alldie Ergebnisse ein und tragen Sie sie in Ihre Frage ein. Echo ist eine Eigenschaft, die ausgeschaltet wird. Vim wird dies tun, während es läuft, und es wird auch das Terminal in den Raw-Modus versetzen. Wenn es beendet wird, sollte es die Terminaleinstellungen selbst zurücksetzen. Wenn vim ausgeführt wird, möchten Sie den iBefehl, der den Editor beispielsweise in den Einfügemodus versetzt, nicht wiederholen. Diese Einstellungen teilen dem tty-Gerät mit, wie es das verarbeiten soll, was Sie eingeben. Während vim läuft, wird darauf geachtet, dass wiedergegeben wird, was wiedergegeben werden soll usw.
John S Gruber
Ich habe die gleichen Symptome, wenn ich Zope stoppe (mit STRG + C), wenn es im Vordergrund läuft und ich mich in einer IPDB-Debugsitzung befinde.
Mark van Lent
@ MarkvanLent Ich glaube, ich habe auch dieses Problem
Niels Bom
@JohnSGruber Ich habe die Ausgabe von stty --allzu meiner Frage hinzugefügt . Danke im Voraus!
Niels Bom

Antworten:

68

Wenn Sie eine Shell oder die meisten Programme in einer Shell ausführen, wird alles, was Sie eingeben, vom tty-Subsystem des Kernels an das Terminal des Benutzers zurückgesendet. Es gibt auch eine andere spezielle Behandlung für das Löschen von Zeichen, Strg + R, Strg + Z usw.

Bestimmte Programme (insbesondere Editoren), die über eine Befehlszeile ausgeführt werden, benötigen oder möchten dies nicht. Aus diesem Grund signalisieren sie dem Kernel mit einem IOCTL-Aufruf an das tty (Terminal) -Gerät, dass sie dieses Verhalten nicht wollen. Sie wollen auch nicht, dass Sonderzeichen besondere Dinge tun. Stattdessen fragen sie den Kernel nach einem "Raw" -Modus. Insbesondere schalten Editoren wie vim verschiedene "Echoeinstellungen" aus. All dies gilt für reale Terminals auf den seriellen Leitungen eines Computers oder die virtuellen Terminals bei Alt + Strg + F1 oder die wirklich virtuellen Terminals, die Sie erhalten, wenn Sie so etwas wie ein Gnome-Terminal unter einer GUI ausführen.

Solche Programme müssen alle Modi, die sie an der von ihnen verwendeten virtuellen Tty ändern, vor dem Beenden zurücksetzen, entweder durch Eingabe eines Befehls zum Beenden des Editors oder durch Entgegennahme eines Signals (von Strg + C).

Wenn sie das nicht richtig machen, bleibt das tty in dem lustigen Zustand, den Sie entdeckt haben. Da Programme das Terminal möglicherweise nicht zurücksetzen können, wurde der resetBefehl geschrieben, um dem Benutzer die Wiederherstellung zu ermöglichen.

Ich gehe davon aus, dass der Interrupt mit der von Ihnen ausgeführten Python-Software in Konflikt gerät. Ich vermute, dass dieses Programm keine Chance hat, das Terminal zurückzusetzen, oder es einfach nicht schafft.

In dem Fall, in dem ich Ihr Beispiel durchführe, erhalte ich dasselbe Verhalten, das Sie beschreiben. Ich sehe auch die Meldung "Vim: Warnung: Eingang ist nicht von einem Terminal" (er verschwindet, wenn Sie zurücksetzen). Dies liegt daran, dass vim nicht normal über die Shell gestartet wird. Stattdessen haben die Befehle 'grep' und 'xargs' die Standardeingabe verwendet, die normalerweise vom tty belegt wird, um die Dateinamen von greptto an zu übergeben xargs.

In Ihrer veröffentlichten Ausgabe von sehen stty -awir "-echo" und bestätigen, dass dies das Problem ist. Wenn Sie vim so töten würden, dass es das Signal nicht ordnungsgemäß verarbeiten könnte, würden Sie wahrscheinlich dasselbe Problem feststellen.

Das Problem wird an anderer Stelle unter https://stackoverflow.com/questions/3852616/xargs-with-command-that-open-editor-leaves-shell-in-weird-state beschrieben .

Eine Lösung für den vim-Fall ist, xargs zu vermeiden und stattdessen Folgendes zu verwenden:

 vim $(grep foo * -l)

Hier wird die Liste der Dateien von der Shell wie von xargs erstellt, aber die Shell ruft vim auf, das direkt mit dem tty verbunden ist. Es wird eine Warnmeldung an die Fehlerausgabedatei gesendet und vim setzt und setzt die tty-Einstellungen korrekt zurück.

Weitere Referenzen hier und eine weitere interessante hier . Eine andere interessante Lösung ist die Antwort auf https://stackoverflow.com/questions/8228831/why-does-locate-filename-xargs-vim-cause-strange-terminal-behaviour .

John S Gruber
quelle
Danke für die ausführliche Erklärung. Der vollständige Grund, warum dies nicht funktioniert, sieht aus wie ein ziemlich tiefes Kaninchenloch (tty, ioctl usw.), daher kann ich nicht sagen, dass ich es vollständig verstehe, aber es ist kein Voodoo mehr. Nochmals vielen Dank!
Niels Bom
Vollständig kann ich grep foo * -l | vim -ohne Probleme ausführen . Ich denke, das Problem liegt nicht bei grep und xargs, sondern nur bei xargs. Würdest du zustimmen?
Niels Bom
1
Mit grep oder xargs ist das kein Problem. Es ist ein Problem mit der Tatsache, dass stdin nicht mehr auf tty gesetzt ist. Dies schlägt ebenfalls fehl vi / tmp / afile1. Eine der Referenzen erwähnt, dass vim stdin auf stdout setzt (immer noch tty), weil stdin in diesen Situationen auf / dev / null gesetzt wurde. Wenn dies der Fall ist, kann sich vim das Echo und andere Einstellungen merken und zurücksetzen, tut dies jedoch nicht. Ich denke das ist ein Problem mit vim.
John S Gruber
Dies war sehr hilfreich, da ich darauf gestoßen bin. Es fühlte sich zufällig an, aber ich wette, es war immer dann, wenn ich versuchte, etwas mit vi zu machen, das nicht sauber herauskam oder eine Pfeife benutzte.
Michael Mathews
1
Danke! Schließlich herausgefunden, wie auf OS X Bash nach einem Strg-C zu erholen git add -p!
Steve Jansen
0

Ich würde einen neuen Benutzer auf dem System starten (ich meine, einen neuen sauberen Benutzer erstellen und mich dort anmelden) und prüfen, ob das Problem vorliegt. Wenn nicht, dann sind es entweder Ihre Terminal- oder Ihre X11-Einstellungen.

Adobe
quelle
Ich habe einen neuen Benutzer hinzugefügt und dies mit dem grep foo * -l | xargs vimBefehl getestet . Das Problem besteht immer noch. Ich verstehe nicht genau, wie meine X11-Einstellungen die Reaktion meines Terminals beeinflussen können. Könnten Sie das näher erläutern? Vielen Dank!
Niels Bom