O shell não mostra os comandos digitados, o “reset” funciona, mas o que aconteceu?

43

Meu problema é que o shell Bash para de mostrar os caracteres que eu digito nele. Ele lê os comandos embora.

Eu me deparei com esse problema algumas vezes e não entendo o que o causa. Eu sei como resolver isso, mas eu realmente não gosto quando estou "vodendo" a minha maneira de sair de problemas.

Vou descrever as duas maneiras pelas quais me deparei com este problema:

Estou executando um determinado processo, link e, às vezes, quando eu o interrompo ou o controle de interrupções é devolvido ao shell. Quando eu entro e digito comandos no shell, os caracteres que eu digito não aparecem. Quando pressiono, digite os comandos são enviados. Então, por exemplo:

  • eu digite "ls"
  • vejo apenas um prompt vazio e nada mais
  • Eu pressiono enter e recebo uma listagem dos arquivos, em outras palavras: o comando é executado
  • quando eu dou o comando "reset", o shell começa a funcionar normalmente novamente

A segunda maneira que isso acontece é quando eu dou um comando assim:

$ grep foo * -l | xargs vim

Eu uso o grep para encontrar arquivos que possuem um certo padrão e, em seguida, quero abrir todos os arquivos que resultam do grep. Isso funciona como um encanto (embora não tão rápido quanto eu esperava). Mas quando eu saio do Vim meu shell para de mostrar os caracteres que eu digito nele. Um comando reset resolve o problema.

Meu palpite é que ambos os problemas têm uma razão subjacente, mas estou meio que confuso sobre como ou o que é essa razão.

A procura por este problema é problemática porque a descrição é um pouco vaga e não tem termos de pesquisa difíceis para ela.

Editar

Dando o

stty --all
O comando

de acordo com o pedido de John S. Gruber deu a seguinte saída (espaço em branco editado para legibilidade)

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
    
por Niels Bom 03.08.2012 / 10:15

2 respostas

48

Ao executar um shell ou a maioria dos programas em um shell, qualquer coisa que você digitar será retornada ao terminal do usuário pelo subsistema tty do kernel. Há outro tratamento especial, também, para apagar caracteres, Ctrl + R, Ctrl + Z e assim por diante.

Certos programas (em particular do editor) executados a partir de uma linha de comando não precisam ou querem isso. Por essa razão, eles sinalizam ao kernel com uma chamada IOCTL contra o dispositivo tty (terminal) que eles não querem esse comportamento. Eles também não querem que personagens especiais façam coisas especiais. Em vez disso, eles pedem ao kernel por um modo "bruto". Em particular, editor's como vim desligam várias "configurações de eco". Tudo isso se aplica a terminais reais em linhas seriais de um computador, ou aos terminais virtuais em Alt + Ctrl + F1, ou aos terminais realmente virtuais que você obtém quando executa algo como o gnome-terminal sob uma GUI.

Tais programas devem reconfigurar quaisquer modos que eles mudem no virtual tty que estão usando antes de sair, seja digitando um comando quit editor ou tomando um sinal (de Control + C), por exemplo.

Se eles não conseguirem fazer isso corretamente, o tty é deixado no estado engraçado que você descobriu. Como os programas podem falhar ao redefinir o terminal, o comando reset foi gravado para permitir que o usuário se recupere.

Eu assumo que a interrupção está mexendo com o software python que você está executando. Eu acho que esse programa não está tendo a chance de redefinir o terminal, ou simplesmente está falhando em fazê-lo.

No caso do vim, quando executo o seu exemplo, recebo o mesmo comportamento que você descreve. Eu também vejo uma mensagem "Vim: Aviso: a entrada não é de um terminal" (ele vai embora quando você redefinir). Isso ocorre porque o vim não é iniciado normalmente a partir do shell. Em vez disso, os comandos 'grep' e 'xargs' usavam a entrada padrão, normalmente ocupada pelo tty, para propósitos de passar os nomes dos arquivos de grep para xargs .

Na sua saída publicada de stty -a , podemos ver "-echo", confirmando também que esse é o problema. Se você fosse matar o vim de tal maneira que ele não pudesse lidar com o sinal graciosamente, você provavelmente veria o mesmo problema.

O problema é descrito em outro lugar em link .

Uma solução para o caso vim é evitar xargs e usar em seu lugar:

 vim $(grep foo * -l)

Aqui a lista de arquivos é construída pelo shell, como tinha sido por xargs, mas o shell está chamando o vim, que está diretamente conectado ao tty. Há uma mensagem de aviso enviada ao arquivo de saída de erro e o vim define e redefine as configurações do tty corretamente.

Mais referências aqui e outra interessante here . Outra solução interessante é dada em uma resposta a link .

    
por John S Gruber 06.08.2012 / 23:16
0

Eu começaria um novo usuário no sistema (quero dizer, fizesse um novo usuário limpo e login lá), e veja se o problema está lá. Se não é - então é o seu terminal ou as configurações do seu X11.

    
por Adobe 03.08.2012 / 16:43