Um script que escrevi faz alguma coisa e, no final, acrescenta algumas linhas ao seu próprio arquivo de log. Eu gostaria de manter apenas as últimas n linhas (digamos, 1000 linhas) do arquivo de log. Isso pode ser feito no final do script desta maneira:
tail -n 1000 myscript.log > myscript.log.tmp
mv -f myscript.log.tmp myscript.log
mas existe uma solução mais limpa e elegante? Talvez realizado através de um único comando?
text-processing
tail
logs
dr01
fonte
fonte
logrotate
é a solução eleganteRespostas:
É possível assim, mas, como já foi dito, a opção mais segura é a geração de um novo arquivo e, em seguida, a movimentação desse arquivo para substituir o original.
O método abaixo carrega as linhas no BASH, portanto, dependendo do número de linhas
tail
, isso afetará o uso de memória do shell local para armazenar o conteúdo das linhas de log.O abaixo também remove as linhas vazias, caso existam no final do arquivo de log (devido ao comportamento da avaliação do BASH
"$(tail -1000 test.log)"
), para não fornecer um truncamento 100% exato em todos os cenários, mas, dependendo da sua situação, pode ser suficiente.fonte
O utilitário
sponge
foi projetado apenas para este caso. Se você o tiver instalado, suas duas linhas poderão ser escritas:Normalmente, a leitura de um arquivo ao mesmo tempo em que você está gravando nele não é confiável.
sponge
resolve isso não escrevendo paramyscript.log
depoistail
que terminar de ler e terminar o pipe.Instalar
Para instalar
sponge
em um sistema semelhante ao Debian:Para instalar
sponge
em um sistema RHEL / CentOS, adicione o repositório EPEL e faça:Documentação
De
man sponge
:fonte
sponge
. Muito útil para todos aqueles que aprendi da maneira mais difícil que você não pode fazersort importantfile.txt > importantfile.txt
:)definitivamente "tail + mv" é muito melhor! Mas para o gnu sed podemos tentar
fonte
Para o registro, com
ed
você poderia fazer algo comoIsso é aberto
infile
er
finalizado na saída detail -n 1000 infile
(ou seja, ele insere essa saída antes da 1ª linha) e exclui do que era inicialmente a 1ª linha até o final do arquivo. Substitua,p
porw
para editar o arquivo no local.Lembre-se de que as
ed
soluções não são adequadas para arquivos grandes.fonte
O que você pode fazer no seu script é implementar a lógica da rotação de log. Faça todo o log através de uma função:
Esta função, em primeiro lugar, faz algo como:
depois, verifica o tamanho do arquivo ou decide de alguma forma que o arquivo requer rotação. Nesse ponto, o arquivo
logfile.1
, se existir, é removido, o arquivologfile.0
, se existir, é renomeado paralogfile.1
elogfile
renomeado paralogfile.0
.A decisão de alternar pode ser baseada em um contador mantido no próprio script. Quando atinge 1000, é redefinido para zero.
Se sempre for necessário aparar estritamente 1000 linhas, o script poderá contar o número de linhas no arquivo de log quando for iniciado e inicializar o contador de acordo (ou se a contagem já atender ou exceder 1000, faça a rotação imediatamente).
Ou você pode obter o tamanho, como com
wc -c logfile
e fazer a rotação com base em exceder um determinado tamanho. Dessa forma, o arquivo nunca precisa ser verificado para determinar a condição.fonte
Eu usei, em vez de
mv
, ocp
comando para conseguir que você possa ter alguns arquivos de log no local em que um software está sendo executado. Talvez no diretório inicial do usuário diferente ou no diretório do aplicativo e tenha todos os logs em um só lugar como links físicos. Se você usar omv
comando, perderá o link físico. Se você usar ocp
comando, manterá esse link físico.meu código é algo como:
Portanto, se os arquivos estiverem no mesmo sistema de arquivos, você também poderá conceder direitos diferentes aos usuários e
${LOGFILE_DIR}
modificar o tamanho como eu.Se for o
mv
comando, você perde o hardlink entre os arquivos e, portanto, seu segundo arquivo não está mais conectado ao primeiro - talvez colocado em outro lugar.Se, em outro lugar, você não permitir que alguém apague o arquivo, seus logs permanecerão juntos e serão bem controlados por meio de seu próprio script.
logrotate
talvez melhor. Mas estou feliz com esta solução.Não se perturbe com o "", mas no meu caso existem alguns arquivos com espaços e outras letras especiais. Se eu não fizer o "" por aí ou o {}, o lote todo não funcionará bem.
Por exemplo, há um diretório em que arquivos mais antigos são automatizados compactados em um
OLDFILE.zip
arquivo e tudo o que é compactado também é listado em Arquivo,.zip_log
portanto, também.zip_log
está neste diretório, mas noLOGFILE_DIR
que eu tenho com:o arquivo igual, pois é um link físico.
fonte