Como limitar o número de linhas que a saída de um comando tem disponível no bash?

11

Comecei a baixar um grande arquivo em segundo plano usando

$ nohup wget http://example.tld/big.iso &

o que também me fornece um nohup.outarquivo que inclui a saída de wget.

Agora, se mais tarde eu quiser assistir ao processo de download, eu poderia usar, $ tail -f nohup.outmas isso preenche minha janela do terminal mais rápido do que eu gostaria. O que eu gostaria de ver é a última linha em constante atualização (assim como no uso wgetsozinho).

Eu tentei, $ tail -n 1 -f nohup.outmas parece afetar apenas a cauda inicial.

De um modo geral, se for possível limitar (neste caso a 1) o número de linhas que a saída de um comando tem disponível / visível, isso resolveria esse problema. É como ter a saída em um buffer circular - basta pensar na barra de progresso normal que $ wget example.tld/big.isoseria impressa.

Existe essa solução?

Ou estou subindo na árvore de maneira errada? (Ou seja, seria mais fácil limitar nohupa produção ou fazer outra coisa?)

Jari Keinänen
fonte

Respostas:

10

Se você não deseja limitar a região de rolagem (veja minha outra resposta), também pode usar o retorno de carro para voltar ao início da linha antes de imprimir a próxima linha. Há uma sequência de escape que limpa o restante da linha, necessária quando a linha atual é mais curta que a linha anterior.

nohup wget http://cdimage.debian.org/debian-cd/6.0.3/amd64/iso-dvd/debian-6.0.3-amd64-DVD-1.iso &
el="$(tput el)"; # Clear to the end of the line
tail -n 1 -f nohup.out | while read -r line; do echo -n $'\r'"$el$line"; done;
janmoesen
fonte
6

Você pode usar watchaqui:

watch -n 0.5 -e "tail -n 1 nohup.out"

Edit : A opção -e(alias --exec) parece adequada aqui. Especialmente se você pretende executar watchcom intervalos muito pequenos, isso reduz a sobrecarga causada pela execução sh -cinterna watchem cada ciclo.

rozcietrzewiacz
fonte
2
Observe que isso gera um novo tailprocesso a cada segundo, que pode ou não ser algo importante para você. Além disso, certifique-se de especificar um intervalo de segundos (por exemplo watch -n 0.1) para simular a parte "atualização constante". (Isso obviamente aumenta também o número de processos e as chamadas de abertura de arquivo.) Finalmente, se você estiver usando o OS X, poderá obter o watchMacPorts, pois ele não está disponível por padrão.
21411 janmoesen
Isso é um pouco complicado, mas ótimo como tal. Eu estava esperando uma resposta que não fosse de tela cheia, para ver as saídas anteriores - mas na verdade eu poderia usar watchem uma nova janela do terminal. Também descobri que usar tail -n 2é mais útil do que -n 1com wget, pelo menos com watchintervalo de 1 segundo, porque, caso contrário, a porcentagem mais recente pode não ser vista; isso não é uma falha na sua resposta, mas eu mencionei isso se outra pessoa decidir assistir à saída do nohup.
Jari Keinänen 21/10
@janmoesen Para esse cenário específico, ter um novo tailprocesso provavelmente não é muito exagero; mas, como resposta geral, é bom levar isso em consideração. Também observei que watch -n 0.1não funcionou, mas watch -n 0,1funcionou - pode haver localidades aplicadas, embora eu não tenha visto localidades aplicadas às opções de comando do terminal antes. Como uma nota lateral: brew install watchfuncionou muito bem :-)
Jari Keinänen
Uma observação lateral: se watchirá funcionar com 0,1ou 0.1depende das configurações do seu código de idioma (ele usa o símbolo decimal definido para o seu código de idioma). Verifique LC_ALL=C watch -n 0.1 "date +%S.%N".
rozcietrzewiacz
3

Existem certas seqüências de controle do Xterm que você pode usar para limitar as linhas do seu terminal que são roladas. Procure por "Definir região de rolagem". No entanto, é um pouco de confusão. Certifique-se de redefinir seu terminal posteriormente:

nohup wget http://cdimage.debian.org/debian-cd/6.0.3/amd64/iso-dvd/debian-6.0.3-amd64-DVD-1.iso &
clear; echo -n $'\e[1;2r'; tail -f nohup.out | grep --line-buffered .
# The "grep" line is to ensure a single line; you can also use "awk 1" or "sed" etc.
janmoesen
fonte
<Inserir a nota de costume sobre a não-portabilidade aqui>
janmoesen
Essa é outra ótima alternativa, mas também é melhor usada em janelas dedicadas, pois tail -fainda preenche o buffer e também porque o terminal precisa ser reiniciado posteriormente. Isso não é tão inline quanto eu esperava, mas, caso contrário, pode ser o que eu procurei.
Jari Keinänen 21/10
0

Se você não deseja que a saída ocupe toda a janela atual do terminal, use um whileloop simples :

while true; do 
  XXX=$( tail -n1 my.log )
  echo -en " \r$XXX\r"
  sleep 0.5
done; echo
rozcietrzewiacz
fonte
1
Observe que, para poder rolar a saída do terminal enquanto estiver executando qualquer comando de produção, é necessário editar as configurações do emulador de terminal e desativar a opção scrollTtyOutput(ou similar).
rozcietrzewiacz