Remova as primeiras N linhas de um arquivo de log ativo

26

Existe uma maneira de remover as primeiras Nlinhas de um log que está sendo anexado ativamente por um aplicativo?

Adam Matan
fonte

Respostas:

10

Não, sistemas operacionais como o Linux e seus sistemas de arquivos não prevêem a remoção de dados desde o início de um arquivo. Em outras palavras, o ponto inicial de armazenamento de um arquivo é fixo.

A remoção de linhas do início de um arquivo geralmente é realizada gravando os dados restantes em um novo arquivo e excluindo o antigo. Se um programa tiver o arquivo antigo aberto para gravação, a exclusão desse arquivo será adiada até que o aplicativo feche o arquivo.


Como comentaram os comentadores, pelas razões indicadas na minha frase anterior, você geralmente precisa coordenar a remoção do arquivo de log com os programas que estão escrevendo os logs. Exatamente como você faz isso depende dos programas. Alguns programas fecham e reabrem seus arquivos de log quando você envia um sinal (por exemplo, HUP) e isso pode ser usado para impedir que os registros sejam gravados em um arquivo de log 'excluído', sem interromper o serviço.

Existem muitos utilitários disponíveis para gerenciar o tamanho dos arquivos de log, por exemplo, logrotate

Alguns programas têm seus próprios utilitários. Por exemplo, o servidor da web Apache inclui um utilitário rotatelogs .

RedGrittyBrick
fonte
3
Mas você não deve fazer isso enquanto algo ainda estiver com o arquivo aberto e ainda anexado a ele, porque ele seria gravado no arquivo agora excluído e você perderia essas mensagens de log.
Tarnay Kálmán 27/03
Verdade. Mesmo se você usou o mesmo nome de arquivo.
Hennes
pena que os sistemas operacionais não permitam, isso seria conveniente para os rotadores de log não precisarem recarregar os processos após a rotação: |
Rogerdpack #
25

Eu acho que essa tarefa pode ser realizada com sed

sed -i '1,10d' myfile

iria remover as linhas de 1 r a o 10 th forma de linha do ficheiro.

Eu acho que todo mundo deveria, pelo menos, dar uma olhada neste sed 1 liners .

Observe que isso não funciona para arquivos de log que estão sendo anexados ativamente por um aplicativo (conforme indicado na pergunta).

sed -iirá criar um novo arquivo e 'excluir' o arquivo que está sendo gravado. A maioria dos aplicativos continuará gravando registros de log no arquivo de log excluído e continuará preenchendo espaço em disco. O novo arquivo de log truncado não será anexado. Isso só cessará quando o aplicativo for reiniciado ou for sinalizado para fechar e reabrir seus arquivos de log. Nesse ponto, haverá uma lacuna (faltando registros de log) no novo arquivo de log se houver alguma atividade registrável entre o uso do sed e a reinicialização do aplicativo.

Uma maneira segura de fazer isso seria interromper o aplicativo, usar sed para truncar o log e reiniciar o aplicativo. Essa abordagem pode ser inaceitável para alguns serviços (por exemplo, um servidor Web com alto rendimento e altos requisitos de continuidade de serviço)

l1zard
fonte
2
Você sabe o que acontece com os aplicativos anexados?
Adam Matan
1
Vamos assumir um manipulador de arquivo aberto normal que acrescenta linhas e libera de vez em quando.
Adam Matan 27/03
1
Eu sei o meu caminho em torno do sed, e extrair linhas para um novo arquivo é um acéfalo com o sed. O problema é manter tudo no mesmo arquivo.
Adam Matan 28/03
10
Não, isso não deve funcionar. sed -icria um novo arquivo com o conteúdo editado e o antigo é removido para que você não esteja editando o arquivo ativo: $ ls -i --- 6823554 testfile --- $ sed -i 's/test/final/' testfile --- $ ls -i --- 6823560 testfile------ Verifique como sed -ifunciona. Por que essa resposta errada tem tantos votos positivos?
pabouk
1
A pergunta declara "a partir de um log que está sendo anexado ativamente por um aplicativo". A palavra operativa é "ativamente". Talvez esse esclarecimento tenha sido adicionado depois que sua resposta apareceu. Mas como está, os leitores que gravitam "com mais votos" serão enganados. Só pude votar uma vez.
Scott Prive
5

Não. Uma solução para esse problema genérico de crescimento do arquivo de log é a rotação do log. Isso envolve a movimentação regular (noturna ou semanal, normalmente) de um arquivo de log existente para outro nome de arquivo e começar de novo com um arquivo de log vazio. Após um período, os arquivos de log antigos são descartados.

Consulte: http://www-uxsup.csx.cam.ac.uk/~jw35/courses/apache/html/x1670.htm

Tarnay Kálmán
fonte
2

Esta é uma resposta , não uma solução. Não há solução para a questão. O solicitante declara claramente: "a partir de um log que está sendo anexado ativamente por um aplicativo". Você pode ler para entender mais e pular para o final para obter uma sugestão que faço com base na minha presunção de que esse código não está seguindo as práticas recomendadas de log.

Para ser claro: outras "respostas" aqui oferecem a promessa falsa . Nenhuma renomeação levará o aplicativo a usar o novo arquivo. As informações mais úteis estão ocultas nos comentários feitos para essas respostas incorretas.

Arquivos ATIVOS não são algum tipo de contêiner no qual você simplesmente coloca os dados. Um nome de arquivo aponta para UM inode (início do arquivo) e todo inode possui um ponteiro para outro inode (se houver mais dados). Isso significa que um arquivo gravado continuamente tem um fluxo constante de inodes sendo adicionado a ele, e o que você pensa de um "arquivo" é na verdade uma sequência de log de inodes.

Imagine que você estava rastreando alguém no Google Maps, e essa pessoa poderia se teletransportar para qualquer lugar do mundo, a qualquer momento, e você estava tentando conectar esses pontos.

A ferramenta Linux "truncar" pode descartar dados no final do arquivo, simplesmente andando na árvore de inodes e (no local / tamanho que você designar) descartará todos os ponteiros subseqüentes na pilha. Fazer o inverso - descartar dados no início do arquivo - seria um processo tão complexo e arriscado de reescrever a árvore de inodes em tempo real que ninguém escreverá essas ferramentas para o público, porque elas geralmente falham e levam a perda de dados. O wiki do Inodes é curto, mas explica alguns desses conceitos.

** Meu conselho: inverter esse problema - POR QUE esse aplicativo está se comportando dessa maneira? Existem muitas práticas recomendadas para registro em log, mas geralmente elas estão vinculadas ao que realmente é o seu sistema de registro (syslog, etc.). No núcleo, espera-se que um aplicativo "libere" seu identificador para o arquivo, para que o logrotate (etc) possa manipular o processamento adicional dos dados antigos.

Sempre que ouço "em um arquivo de log ATIVO", solicito imediatamente que essa pessoa me conte a "história especial" por trás deste aplicativo. Geralmente é "o desenvolvedor parou de trabalhar e não podemos alterar o código. Na verdade, é o inverso da segurança, tem seu próprio conjunto de riscos. Mas quero que você queira uma solução que evite tocar no código-fonte. Se esse for o Nesse caso, é necessária uma pergunta mais específica.

Scott Prive
fonte
0

Abrindo em texto sublime A exclusão das linhas e o salvamento do arquivo funcionam de alguma forma, mesmo que o arquivo esteja sendo anexado, mas eu vim aqui para procurar a solução em busca de uma solução de linha de comando, para que eu deixasse essa solução útil, mas inútil aqui !!

Ashok Kumar Sahoo
fonte
-1

Talvez copie, trunque, coloque a cópia de volta no tamanho = 0 e exclua a cópia?

Melhor ainda, copiar a cauda, ​​truncar original, concat-copiar no original.

Você obtém linhas no log no comprimento da cauda, ​​melhor do que um limite de comprimento de bytes.

Alterando detalhes do comentário:

Primeiro, temos um script de logger em Python3, o que você quiser

from time import sleep

idx = 0
while 1 == 1:
    idx = (idx + 1)
    lf = open('tailTrunc.log', 'a')
    lf.write("line to file " + str(idx) + '\n')
    lf.close()
    sleep(0.01)

Então nós temos nosso truncador

#!/usr/bin/env bash

trap "kill 0" EXIT

rm tailTrunc.log
touch tailTrunc.log

python3 logLoop.py &
loggerPID=$!
sleep 1

kill -STOP $loggerPID
tail -10 tailTrunc.log > trimEnd.log
truncate -s 0 tailTrunc.log
kill -CONT $loggerPID
sleep 1

trimEnd.log mostra 80 a 89

log mostra 90 até o fim

De qualquer forma, onde há vontade, há um caminho.

Muitos exemplos mais complicados de consolidadores e como o fluxo de gravação é aberto ou fechado podem precisar de ajustes por núcleo da CPU, etc. basta pausar a gravação e a fila, se você puder no logger o processo de registro etc.

Mestre James
fonte
"de um log que está sendo anexado ativamente por um aplicativo". O problema que sua solução ignora é que o arquivo de log está "permanentemente" em uso pelo aplicativo - o que significa que o inode do arquivo de log permanece em jogo. Sua solução "faz backup" dos dados do arquivo de log, que podem ter usos fora desta questão.
Scott Prive
Obrigado pelo seu comentário e voto negativo? Eu alterei um exemplo rápido e barato como alimento para o pensamento, você terá que pensar mais profundamente sobre sua situação, mas onde houver vontade, haverá um caminho.
Mestre James
Não pense que foi o meu voto negativo, mas acho que o argumento foi destacado nos comentários da outra resposta: se você copiar um arquivo de log, ele não será mais o arquivo de log ativo ... não importa o que você faça. O tratamento de arquivos do aplicativo sempre apontará para o inode do arquivo de log original. Pense desta maneira: você tem um aplicativo que utiliza funções de registro não padrão e adiciona continuamente bytes ao arquivo que foi aberto.
Scott Prive
1
Certo, lamento inferir. Sim, o inode precisa permanecer o mesmo, é por isso que o exemplo / prova fornecido usa truncado e, novamente, depende da situação (opções para todos aparentemente estão escondidas no site comum).
Mestre James