Como truncar a saída de fluxo de um redirecionamento?

1

Eu tenho um processo que gera uma linha para cada atualização de progresso (sidenote: limpa / substitui a linha, sem quebra de nova linha).

Eu quero salvar a última linha desse processo em um arquivo de saída ou truncar o arquivo de saída para manter o tamanho gerenciável.

No momento eu tenho %código% e com um cron eu tentei usar genrtr > genrtr.log mas não funciona. Também > genrtr.log não ajuda, porque o processo pára de atualizar o arquivo.

Eu entendo por que eles não funcionam, mas me pergunto como reestruturá-lo para que ele atenda às minhas necessidades.

Tentei rm genrtr.log , mas aguarda que o processo termine antes de gravar no arquivo.

Esclarecimentos: O processo produz saída a cada 1 segundo e, a menos que o servidor trave, o processo continuará funcionando para sempre.

    
por Sev 13.04.2013 / 12:09

3 respostas

0

eu queria saber qual a frequência da corrida? ....

tente tee para redirecionar a saída para o arquivo de log, é um utilitário usado frequentemente para fazer uma cópia do strem e redirecionar essa cópia para o arquivo de saída

use : 
  command | tee command_result.log 

você poderia ter uma função de monitor em um script wrapper que invoca este programa, o qual excluirá as 10 primeiras linhas depois de algum intreval ....... desta forma, seu arquivo de log não receberá mais do que alguns KB

também se houver espaços inúteis entre você pode usar o utilitário "tr" para espremer ...  exemplo:

Nitin@Kaizen ~
$ df -h | head -1
    Filesystem      Size  Used Avail Use% Mounted on

Nitin@Kaizen ~
$ df -h | head -1 | tr -s ' '
    Filesystem Size Used Avail Use% Mounted on   *** note the squeeze in space 

espero que isso ajude

    
por 13.04.2013 / 19:19
0

Existem algumas coisas que você pode tentar. O mais fácil é apenas imprimir as últimas linhas do arquivo:

tail genrtr.log

Em seguida, quando o processo terminar, exclua o arquivo de log. Outra opção seria substituir periodicamente o arquivo.

  • Inicie o processo em segundo plano:

    genrtr > genrtr.log &
    
  • Substitua o conteúdo do arquivo de log:

    echo > genrtr.log
    

O arquivo agora está truncado, mas continuará sendo atualizado por gentr , para que o próximo relatório de atualização seja gravado nele. Você pode automatizar isso, por exemplo, truncar o arquivo se ele for maior que 1 MB:

while true; 
  do if [ $(stat -c%s genrtr.log) -gt 1000000 ]; then 
    tail genrt.log > /tmp/foo && cat /tmp/foo > genrt.log; 
     fi;
done

Esse pequeno scriptlet será executado até que você o pare ( while true; ) e toda vez que genrtr.log for maior que um MB, ele manterá as últimas linhas e excluirá o restante do arquivo.

ATUALIZAÇÃO:

Como Scott muito corretamente apontou abaixo, se sua saída contiver \r para limpar a linha, tail não funcionará como esperado. Isso, no entanto, deve:

while true; 
  do if [ $(stat -c%s genrtr.log) -gt 1000000 ]; then 
    tail genrt.log | perl -pe 's/.+\r(.+)/$1\n/' > /tmp/foo && cat /tmp/foo > genrt.log; 
     fi;
done

O comando perl exclui tudo antes do último \r e imprime a última "linha" (os dados após o \r e uma nova linha. O resultado deve ser que a linha da lista é mantida, o restante do arquivo é limpo e o arquivo continua a ser preenchido.

    
por 13.04.2013 / 19:27
0

Acredito que isso será muito difícil de ser feito sem modificar genrtrc ou escrever um novo programa. Se você está mais confortável fazendo o último, sugiro este esquema:

int   c;
FILE  *fp;

fp = fopen(log_file, "w");
if (fp == NULL) (Handle errors)
while ((c = getc()) != EOF)
{
    putchar(c);
    if (c ==escape sequence that ends a line)
    {
        fflush(fp);     //You should probably check for errors here, too.
        rewind(fp);
    }
    else
        putc(c, fp);
}

Isso age como uma combinação de tee e tail - lendo a entrada padrão e gravando-a na saída padrão e em um arquivo - com a diferença de que ela mantém apenas a última linha no arquivo. Então você iria correr

genrtr |the_above_program

    
por 18.04.2013 / 00:33