Acrescentando saída a um arquivo ao mesmo tempo truncando-o para N linhas

5

Estou tentando encontrar uma maneira simples de anexar / gravar em um log e, ao mesmo tempo, manter o log reduzido a um tamanho razoável. Eu preferiria não apenas anexar arquivos para sempre, e então ter que ter um script de log de limpeza. Eu não posso enrolar minha cabeça em torno de como eu faria isso graciosamente sem usar algum segundo arquivo como um detentor temporário.

Coisas que eu olhei para referência:

Eu passei pelo guia avançado de scripts link

Saída combinada de dois comandos: Bash - Como enviar dois comandos para o arquivo?

O ideal seria ter algo como (sei que isso não funciona)

(tail-n 1000 foo.log; ./foo.sh) > foo.log

que manteria as últimas 1000 linhas do meu log atual e então acrescentaria minha nova saída para a execução atual do foo.sh.

Não consigo pensar em como usar o redirecionamento de adição > > e limitar o arquivo original sem envolver a chamada para foo.sh em algum outro bar.sh

tail -n 1000 foo.log > tmp.log
mv tmp.log foo.log
./foo.sh >> foo.log

Isso só parece confuso.

Talvez minha resposta seja para que foo.sh não dependa de STDOUT como um lugar para enviar mensagens de log, mas abra o arquivo diretamente.

EDIÇÃO DE SEGUIMENTO:

A opinião predominante é que isso não é recomendado. Uma opinião que eu aprecio. No entanto, o servidor isso está acontecendo está fora do meu controle e realmente não vai estar sob um administrador .... vigilante. É uma caixa onde muitos grupos diferentes possuem partes da caixa, mas ninguém é responsável pela saúde total da caixa. Eu poderia deixar o log construir para sempre, e provavelmente não importaria no tempo, mas eu gostaria de fazer o que puder para reinar, já que eu sei que o administrador final não fará nada. Então, usar o crontab para executar o logrotate está fora de mim. Estou apenas procurando por algo que eu possa fazer com o ponto limitado de um único comando.

    
por Marc 02.09.2010 / 21:35

5 respostas

1

Se a sua versão de sed tiver a opção --in-place , você poderá usá-la. Ele ainda faz um cp e mv , mas está nos bastidores para que o script pareça um pouco menos confuso, dependendo de como você se sente sobre a sintaxe sed . Caso contrário, seu método tail (você perdeu um em sua edição) e o método de anexação é o modo como eu o abordaria.

Outra abordagem usando sed seria manter seu log de cabeça para baixo com a entrada mais recente no começo.

sed -ni '1s/^/New Entry\n/;100q;p' logfile

Isso é tudo o que existe para isso (além de fazer com que "Nova Entrada" seja o que você quer). Isso manterá um arquivo de log de 100 linhas em ordem cronológica inversa. A vantagem é que você não precisa saber quantas linhas estão no arquivo ( tail cuida disso, mas sed não). Isso pressupõe, até certo ponto, que suas entradas de log consistam em uma única linha. Se você está registrando uma quantidade significativa de saída de um script, acho que está de volta para tail e anexar.

Ainda outra opção que pode funcionar bem para uma saída detalhada de várias linhas seria deixar o sistema de arquivos fazer o trabalho para você. Cada entrada de log seria um arquivo separado.

#!/bin/bash
# *** UNTESTED ***
logdir="/path/to/your/log/dir"

# run the script and log its output to a file named with the date and time
script > "$logdir/$(date "+%Y%m%dT%H%M%S").log"

# maintain the logs
# keep the last 100 days of daily logfiles
# (you could keep the last 100 hours of hourly logfiles, for example,
# by using -mmin and doing some math)

# the count is intended to keep old entries from being deleted
# leaving you with nothing if there are no new entries
count=$(find "$logdir" -maxdepth 1 -type f | wc -l)
if (( count > 100 )) 
then
    find "$logdir" -maxdepth 1 -type f -mtime +100 -delete
fi
    
por 03.09.2010 / 03:41
1

Em geral, eu recomendo que você não se preocupe com o tamanho do log. A maneira padrão de gerenciar isso é com o logrotate. Deixe os administradores decidirem quão grande é o tamanho do log. Parte de ser um bom aplicativo * nix que acredito estar aderindo aos padrões comuns, as pessoas ficam irritadas quando um aplicativo faz algo fora do comum.

    
por 02.09.2010 / 21:44
1

É desaconselhável porque não há como excluir a primeira linha de um arquivo sem reescrever o arquivo inteiro. Dependendo do tamanho do arquivo que é uma operação intensiva. Mesmo se você quiser fazer isso, os dois métodos para fazê-lo (em lugar de procurar ou desvincular, recriar) resultarão em não ver novas linhas ou pensar que todas as linhas são novas.

    
por 02.09.2010 / 22:15
0

Eu teria que concordar com Kyle em logrotate et al. Mas se você está decidido a controlá-lo a partir do seu aplicativo, tente usar o Google para algo como: arquivo de log circular do linux

    
por 02.09.2010 / 21:56
0

Aqui está um post semelhante que rendeu duas boas respostas para mim: Transformando um arquivo de log em uma espécie de buffer circular

Eu tive o mesmo problema e estou feliz em usar o ulogbufd .

    
por 12.10.2011 / 16:40

Tags