Script de shell ou comando para extrair trechos de texto e arquivos binários de grandes arquivos de log

3

Eu preciso remover um arquivo binário grande (arquivo PDF) de um arquivo de log grande que é gerado diariamente.Este é seriamente monopolizando o espaço em nossos servidores.Eu preciso remover o PDF grande dos logs para tornar os logs menores e gerenciável

Eu preciso retirar os textos (ou arquivo binário) entre as strings

  • <my:PDF> e </my:PDF>
  • <applicationForm> e </applicationForm>
  • <image> e </image>
  • <extractedSignature> e </extractedSignature>

Não tenho certeza se o utilitário sed pode fazer isso, são arquivos grandes e precisam ser removidos. Eu não estou procurando aconselhamento de rotação de log, apenas um script ou comando que pode remover esses grandes logs de textos entre os caracteres acima. Não sei ao certo como fazer isso. Esses arquivos são bastante grandes. Não tenho certeza de como conseguir isso com sed, cauda, cabeça, tr ou qualquer outra instalação.

    
por Doknik 13.07.2011 / 12:29

4 respostas

2

Parece que seus arquivos de log são, na verdade, um formato XML. Se for esse o caso, então o que você REALMENTE deve estar fazendo é usar um analisador XML. Leia esta famosa resposta StackOverflow se você quer mais algumas informações.

Com base na sua descrição, um analisador baseado em SAX é provavelmente sua melhor aposta: eles são analisadores orientados por fluxo e não requerem que você carregue todo o arquivo na memória. Como você está realizando apenas uma transformação muito simples no XML, o XSLT provavelmente é um bom candidato para isso (e deve ser FAST se você usar xsltproc de libxslt ). Aqui está uma uma resposta SO que demonstra uma técnica potencialmente relevante .

    
por 13.07.2011 / 13:00
1

Se houver várias linhas entre / start / e / end / patterns, você poderá usar intervalos e d .

Em geral

/start/,/end/d

excluirá todas as linhas entre / start / e / end / inclusive.

Crie um arquivo e adicione as seguintes linhas e salve-o como somefile

/<\"my:PDF\">/,/<\"\/my:PDF\">/d
/<\"applicationForm\">/,/<\"\/applicationForm\">/d
/<\"image\">/,/<\"\/image\">/d
/<\"extractedSignature\">/,/<\"\/extractedSignature\">/d

use-o assim

sed -f somefile logfile >prunedfile
    
por 13.07.2011 / 13:51
0

Você deve poder fazer algo assim com o sed:

cat LOG | sed -e "s/<\"my:PDF\">.*<\/\"my:PDF\">/<\"my:PDF\"><\/\"my:PDF\">/g;" > LOGx

Essencialmente, isso diz "Procure o padrão <"my:PDF"> seguido por qualquer número de qualquer caractere seguido pelo padrão </"my:PDF"> e substitua-o pelo padrão <"my:PDF"></"my:PDF"> , faça isso globalmente".

Repita conforme necessário para as outras strings que você precisa substituir.

    
por 13.07.2011 / 13:09
0

Editar logs ativos é complicado e perigoso, então você terá que esperar até que eles são girados fora de serviço. Se isso não for possível, você pode precisar verificar se O programa de logging pode passar a saída para um filtro em vez de gravar em um arquivo.  O filtro pode então remover as entradas indesejadas antes que as informações sejam gravadas no disco. Isso é um pouco mais arriscado, pois se o filtro morrer, as entradas de log serão perdidas.

Infelizmente, as expressões regulares são "gananciosas". Se uma única linha de log tiver dois ou mais campos que você deseja despir sed irá remover tudo entre:

<"my:PDF">.*?<"/my:PDF"><"keeper">.*?<"/keeper"><"my:PDF">.*?<"/my:PDF">

Com uma opção -p (veja man perlrun) o perl pode se comportar de maneira muito parecida com o sed, mas  com a capacidade de pedir expressões regulares não-vorazes (o? in *?):

perl -p -e '\
    s|<"my:PDF">.*?<"/my:PDF">||g; \
    s|<"applicationForm">.*?<"/applicationForm">||g; \
    s|<"image">.*?<"/image">||g; \
    s|<"extractedSignature">.*?<"/extractedSignature">||g; \
           '  huge.log >huge.log~ && \
mv huge.log~ huge.log
    
por 13.07.2011 / 13:38