Shell n'affiche pas les commandes saisies, “reset” fonctionne, mais que s'est-il passé?

57

Mon problème est que le shell Bash ne montre plus les caractères que je saisis. Il lit cependant les commandes.

J'ai rencontré ce problème plusieurs fois et je ne comprends pas ce qui le cause. Je sais comment le résoudre, mais je n'aime vraiment pas quand je «voodoo» ma façon de résoudre les problèmes.

Je vais décrire les deux manières par lesquelles j'ai rencontré ce problème:

J'exécute un certain processus, http://pythonpaste.org/script/ et parfois quand j'arrête ça ou que ça casse, le contrôle est rendu au shell. Quand je vais ensuite taper des commandes dans le shell, les caractères que je tape n'apparaissent pas. Lorsque j'appuie sur entrer, les commandes sont soumises. Donc par exemple:

  • Je tape "ls"
  • Je ne vois qu'une invite vide et rien de plus
  • J'appuie sur entrée et on me donne une liste des fichiers, en d'autres termes: la commande est exécutée
  • quand je donne la commande "reset" le shell commence à fonctionner normalement

La deuxième manière que cela se produit est quand je donne une commande comme ceci:

$ grep foo * -l | xargs vim

J'utilise grep pour trouver les fichiers qui ont un certain motif, puis je veux ouvrir tous les fichiers résultant du grep. Cela fonctionne comme un charme (mais pas aussi vite que je l'espérais). Mais lorsque je quitte Vim, mon shell cesse d’afficher les caractères que je saisis. Une commande de réinitialisation résout le problème.

J'imagine que les deux problèmes ont une raison sous-jacente, mais je ne comprends pas très bien pourquoi ou pas.

La recherche de ce problème est en soi problématique car la description est assez vague et ne contient pas de termes de recherche durs.

Modifier

Donner le

stty --all

commande selon la demande de John S. Gruber a donné le résultat suivant (espace modifié pour la lisibilité)

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
la source
2
Lorsque cela se produit, veuillez entrer stty --allles résultats dans votre question. Echo est une caractéristique de tty en cours de désactivation. Vim le fera en cours d’exécution et mettra également le terminal en mode brut. Quand il se ferme, il devrait réinitialiser les paramètres du terminal. Lorsque vim est en cours d'exécution, vous ne voulez pas faire écho à la icommande qui place l'éditeur en mode insertion, par exemple. Ces paramètres indiquent au périphérique tty comment il doit traiter ce que vous tapez. Pendant que vim est en cours d'exécution, il se charge de faire écho à ce qui devrait être répercuté, etc.
John S Gruber
J'ai les mêmes symptômes lorsque j'arrête Zope (avec CTRL + C) lorsqu'il s'exécute au premier plan et que je suis en session de débogage ipdb.
Mark van Lent
@MarkvanLent Je pense que j'ai aussi ce problème
Niels Bom Le
@JohnSGruber J'ai ajouté le résultat de stty --allà ma question. Merci d'avance!
Niels Bom

Réponses:

68

Lorsque vous exécutez un shell ou la plupart des programmes dans un shell, tout ce que vous tapez est renvoyé au terminal de l'utilisateur par le sous-système tty du noyau. Il existe également d'autres méthodes spéciales pour effacer des caractères, Ctrl + R, Ctrl + Z, etc.

Certains programmes (notamment ceux de l'éditeur) qui s'exécutent à partir d'une ligne de commande n'en ont pas besoin ou ne veulent pas cela. Pour cette raison, ils signalent le noyau avec un appel IOCTL au périphérique tty (terminal) qu'ils ne souhaitent pas ce comportement. Ils ne veulent pas non plus que des personnages spéciaux fassent des choses spéciales. Au lieu de cela, ils demandent au noyau un mode "brut". En particulier, l'éditeur, comme vim, désactive divers "paramètres d'écho". Tout cela s'applique aux terminaux réels sur les lignes série d'un ordinateur, aux terminaux virtuels situés sous Alt + Ctrl + F1, ou aux terminaux réellement virtuels que vous obtenez lorsque vous exécutez quelque chose comme gnome-terminal sous une interface graphique.

Ces programmes sont supposés réinitialiser tous les modes qu'ils changent sur le terminal virtuel qu'ils utilisent avant de quitter, soit en entrant une commande de l'éditeur de sortie, soit en prenant un signal (de Control + C), par exemple.

S'ils ne le font pas correctement, le terminal est laissé dans l'état amusant que vous avez découvert. Comme les programmes peuvent ne pas réussir à réinitialiser le terminal, la resetcommande a été écrite pour permettre à l'utilisateur de récupérer.

Je suppose que l'interruption concerne le logiciel Python que vous utilisez. J'imagine que ce programme n'a pas la possibilité de réinitialiser le terminal ou ne le fait tout simplement pas.

Dans le cas vim, lorsque j'exécute votre exemple, le comportement que vous décrivez est identique. Je vois aussi le message "Vim: Avertissement: l’entrée ne provient pas d’un terminal" (elle disparaît lorsque vous réinitialisez). En effet, vim n’est pas démarré normalement à partir du shell. Au lieu de cela, les commandes 'grep' et 'xargs' ont utilisé l'entrée standard, normalement occupée par le terminal, pour transmettre les noms de fichier de greptto xargs.

Dans votre sortie postée de stty -anous pouvons voir "-echo", confirmant également que c'est le problème. Si vous deviez tuer vim de telle sorte qu'il ne puisse pas gérer le signal avec élégance, vous verriez probablement le même problème.

Le problème est décrit ailleurs à l' adresse https://stackoverflow.com/questions/3852616/xargs-with-command-that-open-editor-leaves-shell-in-weird-state .

Une solution pour le cas vim est d’éviter xargs et d’utiliser plutôt:

 vim $(grep foo * -l)

Ici, la liste des fichiers est construite par le shell, comme par xargs, mais le shell appelle vim, qui est directement connecté au tty. Un message d'avertissement est envoyé au fichier de sortie d'erreur et vim définit et réinitialise correctement les paramètres tty.

Plus de références ici , et une autre intéressante ici . Une autre solution intéressante consiste à répondre à https://stackoverflow.com/questions/8228831/why-does-locate-filename-xargs-vim-cause-strange-terminal-behaviour .

John S Gruber
la source
Merci pour l'explication approfondie. La raison complète pour laquelle cela ne fonctionne pas ressemble à un rabbithole assez profond (tty, ioctl, etc.) et je ne peux donc pas dire que je comprends tout à fait, mais ce n'est plus du vaudou, alors merci encore!
Niels Bom
Pour être complet, je peux exécuter grep foo * -l | vim -sans problèmes. Donc, je pense que le problème n'est pas avec grep et xargs, mais juste avec xargs. Accepteriez-vous?
Niels Bom
1
Ce n'est pas un problème avec grep ou xargs. C'est un problème avec le fait que stdin n'est plus réglé sur le tty. Cela échoue aussi `true | vi / tmp / afile1. Une des références mentionne que vim définit stdin sur stdout (toujours le tty) car stdin a été défini sur / dev / null dans ces situations. Quand cela se produit, vim pourrait se rappeler et réinitialiser l’écho et d’autres paramètres, mais pas. Je pense que c'est un problème avec vim.
John S Gruber
Cela a été très utile car j'ai rencontré ceci. Cela semblait aléatoire, mais je parie que c'était toujours lorsque j'essayais de faire quelque chose avec vi qui ne sortait pas proprement ou n'utilisait pas de pipe.
Michael Mathews
1
Je vous remercie! Enfin découvert comment récupérer sur OS X bash après un ctrl-c to git add -p!
Steve Jansen
0

Je commencerais un nouvel utilisateur sur le système (je veux dire créer un nouvel utilisateur et me connecter ici), et voir si le problème est là. Si ce n'est pas le cas, il s'agit alors des paramètres de Votre terminal ou de Votre X11.

Adobe
la source
J'ai ajouté un nouvel utilisateur et testé cela avec la grep foo * -l | xargs vimcommande. Le problème existe toujours. Je ne comprends pas exactement comment mes paramètres X11 pourraient influencer la réaction de mon terminal. Pouvez-vous développer sur ce sujet? Merci!
Niels Bom