Somente a saída de 10 (ou n) linhas mais recentes de uma saída de comando longa

3

Eu tenho um comando que gera milhares de linhas. Eu realmente preciso dessas linhas para ver o progresso do comando. Mas eu não preciso ver mais do que as 10 linhas mais recentes.

Como posso fazer isso?

Eu já tentei usar pipe e tail . Mas não funcionou. Acabei de receber as últimas dez linhas após o término do comando original:

whatever command that has too much output | tail -f

É importante que o console não seja limpo ou algo assim, porque há algumas informações importantes que são impressas logo antes do comando com a saída longa.
Um exemplo:

echo "Very important information. MUST BE VISIBLE!"

# This gives me about 10,000 lines of output pretty fast!
# This output should be shrinked down to the most recent 10
tar -cvf "Bckup.tar" "folder to backup/"

# More code

Espero que isso seja claro.

EDITAR:

O problema com multitail é que ele ocupa toda a tela. Então, se eu tivesse mais do que apenas uma saída (que eu tenho. Vários comandos com informações importantes são executados antes disso. E eu preciso usá-lo várias vezes).

Algo como executar isso na tela com apenas 10 linhas para exibir seria perfeito. (Eu sei que isso não funciona).

Você pode imaginar que, como há alguma saída de outros comandos. Então eu chamo o comando com a saída longa. Esta saída fica em uma tela que só pode exibir algo como 10 linhas. Depois que o comando é concluído, mais saída vai para o console e isso deve ser bem como a saída normal.

Output
Important Information
Other commands output
----------------------------------------
some lines for the tar command





----------------------------------------
More output
....
....

(Apenas sem as linhas)

    
por BrainStone 25.08.2013 / 21:40

5 respostas

4

Há uma seqüência de escape para terminais ECMA-48 (vt100-ish) que restringe a rolagem para um subconjunto de linhas:

CSI top ; bottom r

Aqui está uma demonstração

# Start with the screen clean and cursor on line 1
clear

# print the non-scrolling banner line
echo Hello world

# set up the scrolling region to lines 2 through 11 and position the
# cursor at line 2
echo -n '^[[2;11r^[[2H'

# Run a command that will produce more than 10 lines, with a slight delay
# so it doesn't happen so fast you can't see it scrolling
perl -MTime::HiRes=sleep -le 'for(1..100) { print; sleep 0.05; }'

# Restore normal scrolling and put cursor on line 12
echo -n '^[[r^[[12H'

Observação: todas as instâncias de ^[ acima devem ser caracteres de escape reais no script. No vi, por exemplo, eles são inseridos no modo de inserção com Ctrl V seguido por Esc .

    
por 26.08.2013 / 01:54
4

Multitail é um tail -f de esteróides. Suas habilidades incluem dividir a tela e mostrar vários arquivos ou comandos.

Se as linhas importantes vierem de um arquivo:

tar -cvf "Bckup.tar" "folder to backup/" | multitail important.txt -j

Se as linhas importantes são a saída de um comando:

tar -cvf "Bckup.tar" "folder to backup/" | multitail -l 'show-stuff --important' -j
    
por 26.08.2013 / 01:16
3

Se bem entendi BrainStone está pedindo por uma "janela de rolagem".

Você pode conseguir isso com Curses e perl:

#! /usr/bin/perl

use strict;
use warnings;
use Curses;

$SIG{INT} = sub { endwin; exit(0); };

initscr();

my $w = newwin(11, COLS(), 10, 1);
$w->scrollok(1);

my $a=0;
while(<>) {
    $a++ if($a < 10);
    $w->addstr($a, 0, $_);
    $w->refresh();
}
endwin;

Isto criará uma "janela de rolagem" na linha 10, com 10 linhas de comprimento, que exibirá a saída de um comando canalizado. Você terá que alterá-lo para atender às suas necessidades, mas a premissa básica está lá. Você pode querer manipular todos os seus comandos shell dentro de perl e ter tudo em um script. Ou você poderia, por exemplo, usar os argumentos de comando para transmitir a string Very important information. MUST BE VISIBLE! ou pode ser um nome de arquivo que contenha as informações importantes. E mostre isso antes que a janela de rolagem seja criada.

Eu fiz uma versão mais detalhada no pastebin , que lida com algumas opções de comando (como tamanho da janela de rolagem, número de linhas no terminal para compensar a janela e um "arquivo de cabeçalho" para exibir antes da saída). Detalhes das opções de comando e alguns comentários adicionais são fornecidos.

Exemplo

Usando o código acima como está, se você colocá-lo em um arquivo chamado scroller.pl , basta definir as permissões dos arquivos para que seja executável:

$ chmod +x scroller.pl

Você pode usá-lo para mostrar a saída de um comando de longa duração da seguinte forma:

$ seq 10000 | scroller.pl

Esta versão sairá quando a saída que está sendo canalizada para o scroller.pl estiver completa, e retornará à sua configuração normal do shell.

    
por 26.08.2013 / 03:46
0

Se você sempre quer ver apenas as últimas N linhas, eu não acho que você possa evitar o uso de um arquivo temporário. Algo parecido com isto:

while true; do sleep 1; date +%s >> temp_file; done

Então, em outro terminal, execute

while true; do clear; tail -n 10 temp_file;sleep 1; done

Esse último comando irá i) limpar o terminal, ii) imprimir as últimas 10 linhas do arquivo temporário e iii) esperar por um segundo. O resultado será um dump continuamente atualizado das últimas 10 linhas atuais do arquivo temporário.

Até onde eu sei, não há como fazer isso enquanto se mantém o comando original à vista em um único terminal.

Não consigo fazer isso funcionar para várias linhas, mas isso funciona para linhas únicas:

#!/bin/bash

echo "Very important information. MUST BE VISIBLE!"
while tar -cvf "Bckup.tar" lmde_backup/www/lycabettus/ >tmp_file 2>&1 & do 
    output=$(tail -n 1 aa); 
    echo -ne "$output\r";
done

Isso resulta em artefatos quando a linha atual é menor do que a anterior, portanto, ela não é perfeita, mas você pode melhorar isso.

    
por 25.08.2013 / 22:16
0

Aqui está um script bash simples que você pode usar para monitorar a saída do seu comando (o comando neste exemplo é rpm -qa ) linha por linha com um temporizador de suspensão manualmente definido. Ele também acrescenta sua saída a um arquivo temporário para referência após a conclusão do script. Quanto a percorrer um buffer de 10 linhas, não consigo pensar em uma solução neste momento.

#!/bin/bash

syntax="rpm -qa"
command=( $($syntax) )
echo "Using: $syntax"
for line in "${command[@]}"
 do
  echo "$line" >> /tmp/temp.file
  echo -ne "OUTPUT: $line3[0K\r"
  sleep 0.2
done
echo


    
por 25.08.2013 / 21:42