Parando a saída de um programa executado na sessão SSH AGORA

17

Problema

Eu executo o comando que gera MUITAS informações através do SSH. Por exemplo, eu adiciono insensatamente informações de depuração dentro de um loop que é executado milhões de vezes, ou apenas execute cat /dev/urandom para pontapés.

O terminal está inundado de informações.

Euqueroencerrarocomandoomaisrápidopossívelecorrigiromeuprograma.Eunãomeimportocomoqueéimpresso.Agora,acoisaéqueeupressionoCtrl+Comaisrápidopossível(noexemploacima,pressioneiimediatamentedepoisdeexecutarocomando),masaindademoraparaimprimirtodasasinformaçõesqueeunempreciso.

Oqueeutentei

EutenteipressionarCtrl+Ccomtantadificuldadequeteveresultadosengraçadosquandooterminalfinalmentecaptou:

OUTPUTHERE^Crr-@burza:~/xor$^Crr-@burza:~/xor$^Crr-@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^Crr-@burza:~/xor$^Crr-@burza:~/xor$^Crr-@burza:~/xor$^Crr-@burza:~/xor$^Crr-@burza:~/xor$^Crr-@burza:~/xor$^Crr-@burza:~/xor$^Crr-@burza:~/xor$^Crr-@burza:~/xor$^C

EutambémlisobreCtrl+Squeaparentemente é usado para dizer ao terminal" stop output, eu preciso recuperar o atraso " mas aparentemente ele não faz nada.

Detalhes diversos

Eu gostaria de não alterar o comando que eu corri para que eu possa me resgatar em qualquer situação, mesmo que eu não me lembre de que o programa que eu corro poderia acabar assim.

Meu cliente SSH é executado no 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 configurado como xterm-256color .

O servidor SSH é executado no Debian ( Linux burza 3.2.0-4-686-pae #1 SMP Debian 3.2.51-1 i686 i686 i686 GNU/Linux ).

    
por rr- 18.06.2014 / 20:11

6 respostas

5

Parte dessa saída será armazenada em buffer. Você envia sua Ctrl + C para a extremidade remota 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 exibido, sua tela mostrará primeiro todos os dados que foram armazenados em buffer e que já estão no seu caminho.

O que você está pedindo é que o programa pare e que os dados em trânsito desapareçam de alguma forma. Isso não pode acontecer porque já está em rota.

A única maneira de certificar-se de que você não vê esses dados é sair do terminal e reconectar-se ao seu controle remoto, mas isso é provavelmente um esforço muito maior do que esperar que os dados em buffer sejam exibidos.

    
por 18.06.2014 / 20:38
9

Eu normalmente executo a saída em less para que eu possa eliminá-la via less usando a tecla q .

$ cmd | less

Exemplo

$ cat /dev/urandom | less

Depoisdepressionarq+Enter,eleseráencerradoeretornaráaoseuterminalnormal,deixando-olimpo.

Porqueissoacontece?

Oproblemaquevocêestáencontrandoéqueexistembuffers(paraSTDOUT)queestãosendoenfileiradoscomasaídadoseumonitor.Essesbufferssãopreenchidostãorapidamentequevocênãoconsegueinterrompê-losrápidoosuficienteparapará-lo.

Para desabilitar / limitar esse efeito, você pode desabilitar o buffer STDOUT, o que deve tornar as coisas um pouco mais responsivas usando stdbuf , mas você provavelmente terá que jogar com essas configurações para fazer as coisas do jeito que você deseja. Para unbuffer STDOUT você pode usar este comando:

$ stdbuf -o0 <cmd>

A página man do 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 um bom histórico sobre como funciona o armazenamento em buffer, sugiro dar uma olhada neste Pixel Beat intitulado: armazenamento em buffer em fluxos padrão . Inclui até imagens agradáveis.

Referências

por 18.06.2014 / 20:26
3

Existem vários níveis de buffering. 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 a uma velocidade muito alta, o terminal não consegue acompanhar e fica lento. Isso é o que está acontecendo aqui: exibir texto é muito mais caro do que produzir esses números aleatórios. Sim, mesmo com uma fonte de bitmap, a produção de números aleatórios com qualidade criptográfica é muito barata em comparação. (Eu apenas tentei na minha máquina e o processo X saturou a CPU, com xterm tomando alguns% e cat (com o qual a geração de número aleatório é contabilizada) chegando a 1%. E isso é com uma fonte de bitmap.)

Se você quiser que isso pare agora, mate 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 X, para que o lixo termine 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 estiver processando os dados em segundo plano.

Quando tudo isso está acontecendo em um shell remoto, o atraso é ainda pior, porque os dados produzidos por cat precisam primeiro passar pela conexão SSH. Sua pressão de Ctrl + C também tem que passar pela conexão SSH; ele recebe uma prioridade mais alta (é enviado fora da banda), mas isso ainda leva algum tempo durante o qual mais saída é acumulada. Não há como suprimir dados em trânsito antes de fechar a conexão SSH (o que você pode fazer pressionando Enter e então ~. ).

    
por 19.06.2014 / 03:07
1

Deve ser o suficiente para encontrar uma maneira de kill o comando cat .
Para as propostas a seguir, você pode precisar de uma segunda conexão ssh aberta.

  • Raramente CTRL + z pode ser mais efetivo que CTRL + c : ele pode responder mais rápido. Depois disso, você suspende o comando e pode matá-lo com kill %1 ou qualquer que seja o número do trabalho.
    Isso na esperança de que você ainda é capaz de ler qualquer coisa da tela (um texto binário aleatório inundação pode facilmente atrapalhar o seu conjunto de caracteres). Conforme lembrado por Gilles se você minimizar a janela, provavelmente o sistema será mais rápido para ler o pedido de interrupção do que você para matar o processo. Então suspender / quebrar, minimizar, esperar um pouco, maximizar novamente, pode ser uma solução também. Claro que através de uma conexão ssh, espero que você precise, no entanto, esperar algum tempo.

  • Em outro terminal / sessão, você pode perguntar ao pgrep cat (se o comando cat foi chamado) e identificar que o processo do cat está usando mais o cpu. Você pode identificá-lo com mais precisão com pstree :

    pgrep cat | awk '{print "pstree -sp" $ 1}' | sh | grep sshd

    responda com uma saída como

    init (1) ───sshd (1062) ───sshd (22884) ───sshd (22951) ───bash (22957) ───Cat (23131)

    Neste caso, depois de ter apenas que matar o gato PID: mate 23131

Nota:

por 19.06.2014 / 12:10
1

Eu tive o mesmo problema e não estava satisfeito com as respostas aqui, então eu cavei mais fundo. Outros já mencionaram que seu comando está emitindo 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 armazenar em buffer limitando a saída do comando para a taxa máxima que sua sessão ssh pode executar, 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, acelere 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 a TAXA um pouco, caso a velocidade de conexão diminua um pouco de vez em quando. Se ele diminuir, o comportamento retornará ao problema, um ctrl-c não responsivo.

Alias de gato otimizado opcional:

# bash
alias tcat='tcat(){ cat $@ | pv -qL 400k ; }; tcat'

# tcsh
alias tcat 'cat \!* | pv -qL 400k'

# usage: tcat <FILENAME>

Agora ctrl-c funciona como esperado, matando imediatamente a saída, já que muito pouco, se é que algum, está em buffer.

    
por 06.02.2018 / 23:01
0

Existe um software no Linux que resolve exatamente esse problema (algumas outras coisas também). Você também pode invocá-lo a partir de um emulador de terminal no Windows (parece que você está usando o Windows?).

Teste mosh , um substituto para o binário SSH. Funciona exatamente como o SSH (você pode fazer mosh user@hostname em vez de ssh user@hostname e ele funcionaria exatamente como o esperado, até mesmo fará a autenticação de chave privada, etc.

Basicamente, ele executa um processo separado no servidor que armazena os pacotes. Então, quando você pressiona Ctrl + C no mosh, ele transmitirá isso para o servidor remoto, que então irá parar de enviar as informações extras. Além disso, ele também prevê o resultado de pressionamentos de teclas, economizando alguns milissegundos cada vez que você pressiona uma tecla.

Desvantagem: atualmente não é possível rolar para cima no histórico ao usar o mosh.

    
por 15.08.2018 / 18:58