Shell non mostra i comandi digitati, "reset" funziona, ma cosa è successo?


57

Il mio problema è che la shell Bash smette di mostrare i caratteri che scrivo al suo interno. Legge i comandi però.

Ho riscontrato questo problema parecchie volte e non capisco cosa lo causi. So come risolverlo, ma davvero non mi piace quando sto "voodooing" il mio modo di risolvere i problemi.

Descriverò i due modi in cui ho riscontrato questo problema:

Sto eseguendo un certo processo, http://pythonpaste.org/script/ e talvolta quando lo interrompo o si rompe il controllo viene restituito alla shell. Quando poi vado e digito i comandi nella shell, i caratteri che scrivo non vengono visualizzati. Quando premo invio vengono inviati i comandi . Quindi per esempio:

  • Digito "ls"
  • Vedo solo un prompt vuoto e nient'altro
  • Premo invio e mi viene fornito un elenco dei file, in altre parole: il comando viene eseguito
  • quando do il comando "reset" la shell ricomincia a funzionare normalmente

Il secondo modo in cui ciò accade è quando do un comando come questo:

$ grep foo * -l | xargs vim

Uso grep per trovare file che hanno un certo schema e quindi voglio aprire tutti i file risultanti da grep. Funziona come un incantesimo (anche se non così veloce come speravo). Ma quando esco da Vim la mia shell smette di mostrare i personaggi che scrivo. Un comando di ripristino risolve il problema.

La mia ipotesi è che entrambi i problemi abbiano una ragione di fondo, ma sono un po 'perplesso su come o quale sia quella ragione.

La ricerca di questo problema è di per sé problematica perché la descrizione è piuttosto vaga e non ha termini di ricerca difficili.

modificare

Dare il

stty --all

il comando secondo la richiesta di John S. Gruber forniva il seguente output (spazi bianchi modificati per la leggibilità)

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

2
Quando ciò accade, inserisci stty --alle inserisci i risultati nella tua domanda. L'eco è una caratteristica tty che viene disattivata. Vim lo farà mentre è in esecuzione e metterà anche il terminale in modalità raw. Quando si chiude dovrebbe ripristinare le impostazioni del terminale stesso. Quando vim è in esecuzione, non si desidera echeggiare il icomando che mette l'editor in modalità di inserimento, ad esempio. Queste impostazioni indicano al dispositivo tty come dovrebbe elaborare ciò che si digita. Mentre vim è in esecuzione, si occupa dell'eco di ciò che dovrebbe essere ripetuto, ecc.
John S Gruber,

Ho gli stessi sintomi quando fermo Zope (con CTRL + C) quando è in esecuzione in primo piano e sono in una sessione di debug ipdb.
Mark van Lent,

@MarkvanLent Penso di avere anche quel problema
Niels Bom il

@JohnSGruber Ho aggiunto l'output stty --allalla mia domanda. Grazie in anticipo!
Niels Bom il

Risposte:


68

Quando si esegue una shell o la maggior parte dei programmi in una shell, qualsiasi cosa digitata viene restituita al terminale dell'utente dal sottosistema tty del kernel. C'è anche un'altra gestione speciale per cancellare i caratteri, Ctrl + R, Ctrl + Z e così via.

Alcuni programmi, (in particolare quelli dell'editor) eseguiti da una riga di comando, non ne hanno bisogno o lo desiderano. Per questo motivo segnalano al kernel con una chiamata IOCTL contro il dispositivo tty (terminale) che non vogliono questo comportamento. Non vogliono nemmeno personaggi speciali per fare cose speciali. Invece chiedono al kernel una modalità "raw". In particolare, l'editor come vim disattiva varie "impostazioni dell'eco". Tutto ciò si applica ai terminali real tty sulle linee seriali di un computer, o ai terminali virtuali su Alt + Ctrl + F1, o ai terminali veramente virtuali che ottieni quando esegui qualcosa come gnome-terminal sotto una GUI.

Tali programmi dovrebbero ripristinare tutte le modalità che cambiano sulla tty virtuale che stanno utilizzando prima di uscire, inserendo un comando di chiusura dell'editor o prendendo ad esempio un segnale (da Control + C).

Se non riescono a farlo correttamente, il tty viene lasciato nello stato divertente che hai scoperto. Poiché i programmi non riescono a ripristinare il terminale, il resetcomando è stato scritto per consentire all'utente di ripristinare.

Suppongo che l'interrupt stia scherzando con il software Python in esecuzione. Immagino che quel programma non abbia la possibilità di ripristinare il terminale, o semplicemente non riesca a farlo.

Nel caso vim, quando eseguo il tuo esempio, ottengo lo stesso comportamento che descrivi. Vedo anche il messaggio "Vim: Attenzione: l'ingresso non proviene da un terminale" (scompare quando si ripristina). Questo perché vim non viene avviato normalmente dalla shell. Invece i comandi 'grep' e 'xargs' hanno usato l'input standard, normalmente occupato da tty, allo scopo di passare i nomi dei file da greptto xargs.

Nel tuo output pubblicato da stty -apossiamo vedere "-echo", confermando anche che questo è il problema. Se dovessi uccidere Vim in modo tale da non poter gestire il segnale con grazia, probabilmente vedresti lo stesso problema.

Il problema è descritto altrove su https://stackoverflow.com/questions/3852616/xargs-with-command-that-open-editor-leaves-shell-in-weird-state .

Una soluzione per il caso vim è evitare xargs e usare invece:

 vim $(grep foo * -l)

Qui l'elenco dei file è costruito dalla shell, come lo era stato da xargs, ma la shell chiama vim, che è direttamente collegata a tty. C'è un messaggio di avviso inviato al file di output dell'errore e vim imposta e ripristina correttamente le impostazioni tty.

Più riferimenti qui e un altro interessante qui . Un'altra soluzione interessante è data in una risposta a https://stackoverflow.com/questions/8228831/why-does-locate-filename-xargs-vim-cause-strange-terminal-behaviour .


Grazie per la spiegazione approfondita. Il motivo completo per cui questo non funziona sembra un rabbithole abbastanza profondo (tty, ioctl, ecc.) Quindi non posso dire di aver capito completamente, ma non è più voodoo, quindi grazie ancora!
Niels Bom,

Per essere completo, posso eseguire grep foo * -l | vim -senza problemi. Quindi penso che il problema non sia con grep e xargs, ma solo con xargs. Sei d'accordo?
Niels Bom,

1
Non è un problema con grep o xargs. È un problema con il fatto che stdin non è più impostato su tty. Anche questo fallisce `vero | vi / tmp / afile1. Uno dei riferimenti menziona che vim imposta stdin su stdout (sempre il tty) perché stdin è stato impostato su / dev / null in queste situtations. Quando lo fa vim potrebbe ricordare e ripristinare l'eco e altre impostazioni, ma non lo fa. Penso che questo sia un problema con vim.
John S Gruber,

Questo è stato molto utile perché mi sono imbattuto in questo. Sembrava casuale, ma scommetto che era sempre quando stavo provando a fare qualcosa con vi che non usciva in modo pulito o utilizzava una pipa.
Michael Mathews,

1
Grazie! Finalmente ho capito come recuperare su OS X bash dopo un ctrl-c a git add -p!
Steve Jansen,

0

Avrei avviato un nuovo utente sul sistema (intendo creare un nuovo utente pulito e accedere lì) e vedere se il problema è presente. Se non lo è, allora è il tuo terminale o le tue impostazioni X11.


Ho aggiunto un nuovo utente e l'ho provato con il grep foo * -l | xargs vimcomando. Il problema esiste ancora. Non capisco esattamente come le mie impostazioni X11 potrebbero influenzare il modo in cui il mio terminale reagisce a proposito. Potresti approfondire questo? Grazie!
Niels Bom il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.