Problema
Eu executo um comando que gera MUITAS informações por meio de SSH. Por exemplo, eu tolamente adiciono informações de depuração dentro de um loop que é executado milhões de vezes, ou apenas corro cat /dev/urandom
para me divertir.
O terminal está inundado de informações.
Quero encerrar o comando o mais rápido possível e consertar meu programa. Eu não me importo com o que isso imprime. Agora, o que acontece é que eu pressiono Ctrl+ CASAP (no exemplo acima pressionei imediatamente após executar o comando), masainda demora para imprimir todas as informações que eu nem preciso.
O que eu tentei
Tentei pressionar Ctrl+ Ccom tanta força que tive resultados engraçados quando o terminal finalmente alcançou:
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
Eu também li sobre Ctrl+ Sque aparentementeé usado para dizer ao terminal "pare a saída, preciso atualizá-la"mas aparentemente não faz nada.
Detalhes diversos
Gostaria de não alterar o comando que executo para poder me resgatar em qualquer situação, mesmo que não me lembre que o programa que executo pode acabar assim.
Meu cliente SSH é executado em Cygwin( CYGWIN_NT-6.1-WOW64 luna 1.7.30(0.272/5/3) 2014-05-23 10:36 i686 Cygwin
) no MinTTY com o tipo de terminal definido como xterm-256color
.
Servidor SSH roda em Debian ( Linux burza 3.2.0-4-686-pae #1 SMP Debian 3.2.51-1 i686 i686 i686 GNU/Linux
).
Responder1
Eu normalmente executo a saída less
para poder eliminá-la less
usando a qchave.
$ cmd | less
Exemplo
$ cat /dev/urandom | less
Depois de pressionar q+ Enterele será encerrado e retornará ao seu terminal normal, deixando-o limpo e limpo.
Por que isso acontece?
O problema que você está encontrando é que existem buffers (para STDOUT) que estão sendo enfileirados com a saída do seu display. Esses buffers são preenchidos tão rapidamente que você não consegue interrompê-los com rapidez suficiente para interrompê-los.
Para desabilitar/limitar esse efeito, você pode desabilitar o buffer STDOUT, que deve tornar as coisas um pouco mais responsivas usando stdbuf
, mas provavelmente você terá que brincar com essas configurações para fazer as coisas do jeito que deseja. Para remover o buffer STDOUT você pode usar este comando:
$ stdbuf -o0 <cmd>
A página de manual stdbuf
detalha as opções à sua disposição:
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.
Para ter uma boa ideia de como funciona o buffer, sugiro dar uma olhada neste artigo do Pixel Beat intitulado:buffer em fluxos padrão. Inclui até belas fotos.
Referências
Responder2
Parte dessa saída será armazenada em buffer. Você envia seu Ctrl+ Cpara o terminal remoto, o que interrompe o programa em execução. O programa existe e o shell envia os caracteres para mostrar o prompt novamente. Antes que o prompt seja mostrado, sua tela mostrará primeiro todos os dados que foram armazenados em buffer e já estão a caminho de você.
O que você está pedindo é que o programa pare e os dados em trânsito desapareçam de alguma forma. Isso não pode acontecer porque já está a caminho.
A única maneira de ter certeza de que não verá esses dados é sair do terminal e reconectar-se ao controle remoto - mas isso provavelmente exige muito mais esforço do que esperar que os dados em buffer sejam exibidos.
Responder3
Existem vários níveis de buffer. Quando você pressiona Ctrl+ C, isso impede que o programa emita dados para o terminal. Isso não afeta os dados que o emulador de terminal ainda não exibiu.
Quando você exibe dados em alta velocidade, o terminal não consegue acompanhar e fica atrasado. É isso que está acontecendo aqui: exibir texto é muito mais caro do que produzir esses números aleatórios. Sim, mesmo com uma fonte bitmap – produzir números aleatórios com qualidade criptográfica é muito barato em comparação. (Eu apenas tentei na minha máquina e o processo X saturou a CPU, levando xterm
alguns% e cat
(contra o qual a geração de números aleatórios é contabilizada) mal chegando a 1%. E isso é com uma fonte de bitmap.)
Se você quiser que isso pare agora, elimine o emulador de terminal. Se você não quiser fazer isso, pelo menos minimize a janela; emuladores de terminal inteligentes (como o xterm) não mapearão a janela, o que economiza o tempo da CPU do X, então o lixo terminará de ser exibido mais rapidamente. O servidor X tem alta prioridade, então isso fará uma grande diferença na capacidade de resposta da sua máquina enquanto o xterm processa os dados em segundo plano.
Quando tudo isso acontece em um shell remoto, o atraso é ainda pior, pois os dados produzidos cat
precisam primeiro passar pela conexão SSH. Pressionar Ctrl+ Ctambém precisa passar pela conexão SSH; ele recebe uma prioridade um pouco mais alta (é enviado fora da banda), mas ainda leva algum tempo durante o qual mais saída se acumula. Não há como suprimir dados em trânsito antes de fechar a conexão SSH (o que você pode fazer pressionando Enterentão ~.
).
Responder4
Eu tive o mesmo problema e não fiquei satisfeito com as respostas aqui, então fui mais fundo. Outros já mencionaram que seu comando está gerando dados mais rápido do que o seu ssh pode suportar, portanto, os buffers de dados e os buffers não podem ser interrompidos.
Para corrigir isso, evite o buffer limitando a saída do comando para a taxa máxima que sua sessão ssh pode suportar; já existem comandos para fazer isso.
Configuração, primeiro descubra a taxa máxima de suas sessões:
# 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
Finalmente, limite seus comandos reais de acordo.
<YOUR_COMMAND> | pv -qL <RATE>
Exemplo:
/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
Você pode querer reduzir um pouco a TAXA caso a velocidade da sua conexão caia um pouco de vez em quando. Se cair, o comportamento retornará ao problema, um ctrl-c que não responde.
Alias opcional de gato estrangulado:
# bash
alias tcat='tcat(){ cat $@ | pv -qL 400k ; }; tcat'
# tcsh
alias tcat 'cat \!* | pv -qL 400k'
# usage: tcat <FILENAME>
Agora ctrl-c funciona conforme o esperado, eliminando imediatamente a saída, já que muito pouco ou nenhum está armazenado em buffer.