Transformando um arquivo de log em uma espécie de buffer circular

22

Pessoal, existe uma solução * nix que faria o arquivo de log funcionar como um buffer circular? Por exemplo, eu gostaria que os arquivos de log armazenassem no máximo 1 GB de dados e descartassem as entradas mais antigas assim que o limite fosse atingido.

É possível de alguma forma? Acredito que para conseguir que um arquivo de log seja transformado em algum tipo de dispositivo especial ...

PS: Estou ciente das ferramentas diversas de logrotating, mas não é disso que preciso. A criação de log exige muita IO, normalmente acontece uma vez ao dia, enquanto eu preciso de uma solução de "tempo de execução".

pachanga
fonte
3
Não sei por que você acha que a rotação de logs precisaria de muito IO. Girar 10 arquivos de log é 10 operações de renomeação e um HUP do serviço. Não é exatamente uma operação assassina ... E é a solução padrão para o problema :)
pehrs
2
Pode-se estar executando um script / executável que não funciona bem com o HUP.
21711 Scott
11
Isso serve para fornecer outro caso de uso para sua pergunta. Eu tenho um tocador de música demonizado. Eu quero um registro de comprimento apenas várias linhas, para que eu possa ver o que está tocando e o que tocou antes disso. A tail -f somefilefaria isso. Eu apenas tentei com logs girados e tail -fnão funciona com eles.
Vorac

Respostas:

14

O Linux possui um buffer de anel do kernel. Você pode usar dmesgpara exibi-lo .

Ou aqui está um módulo do kernel Linux que parece fazer o que você deseja.

O que é emlog?

O emlog é um módulo do kernel do Linux que facilita o acesso à saída mais recente (e somente a mais recente) de um processo. Funciona exatamente como "tail -f" em um arquivo de log, exceto que o armazenamento necessário nunca aumenta. Isso pode ser útil em sistemas incorporados onde não há memória ou espaço em disco suficiente para manter arquivos de log completos, mas as mensagens de depuração mais recentes são necessárias algumas vezes (por exemplo, após a observação de um erro).

O módulo do kernel emlog implementa um driver de dispositivo de caracteres simples. O driver age como um pipe nomeado que possui um buffer circular finito. O tamanho do buffer é facilmente configurável. À medida que mais dados são gravados no buffer, os dados mais antigos são descartados. Um processo que lê de um dispositivo emlog primeiro lê o buffer existente e, em seguida, vê o novo texto conforme é escrito, semelhante ao monitoramento de um arquivo de log usando "tail -f". (Leituras sem bloqueio também são suportadas, se um processo precisar obter o conteúdo atual do log sem bloquear para aguardar novos dados.)

Pausado até novo aviso.
fonte
11
Obrigado pelo link! BTW, a página inicial do emlog tem um link para ulogbufd, que provavelmente é uma solução ainda mais apropriada para mim.
Pachanga
O módulo do kernel emlog agora é mantido no github: github.com/nicupavel/emlog
dbernard
4

A coisa mais próxima que consigo pensar é no RRDTools, mas provavelmente não é o que você está procurando. Outra solução seria monitorar o arquivo de log (digamos a cada segundo ou no Linux com inotify), por exemplo, você escreve um script como:

while :; do
  if [[ $(stat -c %s $FILE) -gt 10000 ]]; then
    # rotate the log
  fi
  sleep 1
done

com inotify:

while :; do
  if inotifywait [some options] $FILE; then
    # check size and rotate the file
  fi
done
Dan Andreatta
fonte
+1 por mencionar RRDtool, um exemplo real de log da estrutura de dados em anel.
Cory J
Obrigado por exemplo mostrando o uso do comando shell inotifywait
pachanga
4

Você pode usar o multilog no Daemontools do djb. Você canaliza sua saída de log para ele. Sim, é rotação de log, mas as rotações são simplesmente:

ln current $tai64nlocaltimestamp

O que, em praticamente qualquer sistema de arquivos linux moderno, é uma operação super rápida. Você pode especificar quantos arquivos de log deseja e qual o tamanho que deseja. faça 10 x 1024mb arquivos e você terá seu buffer de anel de 1GB.

Observe que, devido à rotação automática, é uma fonte por instância multilog. Mas você pode contornar isso escrevendo um invólucro simples com o netcat ou manualmente.

Jason
fonte
Obrigado pela dica! Definitivamente vou ter também no multilog.
pachanga
1

Você pode criar um canal FIFO e, a partir daí, lê-lo usando um script que insere em um banco de dados. Quando o contador atingir 1.000, reinicie o número de identificação que está sendo inserido no banco de dados. É claro que não funcionaria para o tamanho, mas você usou isso como exemplo, então estou assumindo que essa é uma questão teórica.

sinping
fonte
1

Pergunta interessante; você normalmente não vê isso como um design. Eu tenho um programa que usa uma técnica levemente semelhante para registrar o histórico, mas ele usa um formato binário. O 'arquivo de log' possui quatro partes, todas dispostas em um formato neutro à máquina:

  1. Um cabeçalho contendo o número mágico e o número (máximo) de entradas na lista usada e na lista livre, o número de sequência para a próxima entrada no histórico, o número real de entradas na lista usada, o número real de entradas na lista livre e o comprimento do arquivo (cada um com 4 bytes).
  2. A lista usada, cada entrada fornecendo um deslocamento e um comprimento (4 bytes para cada parte de cada entrada).
  3. A lista livre, cada entrada semelhante à entrada da lista usada.
  4. Os dados principais, cada registro de histórico que consiste em um conjunto contíguo de bytes finalizados por um byte de terminador nulo.

Quando um novo registro é alocado, se houver espaço na lista livre, ele substitui uma entrada lá (não necessariamente usando tudo - nesse caso, o fragmento permanece na lista livre). Quando não há espaço na lista livre, o novo espaço é alocado no final. Quando um registro antigo é rotacionado, seu espaço é movido para a lista livre e unido a quaisquer registros livres adjacentes. Ele foi projetado para lidar com instruções SQL, para que os registros possam se espalhar por muitas linhas. Este código funciona em um número especificado de registros. Ele não limita o tamanho do arquivo em si (embora não seja difícil fazê-lo).

O código principal do histórico de código está em dois arquivos, history.c e history.h, disponíveis na fonte do programa SQLCMD (minha versão, não da Microsoft; a minha existia uma década ou mais antes da Microsoft), que pode ser baixada em Arquivo de Software do Grupo Internacional de Usuários Informix . Também existe um programa de despejo de arquivo de histórico (histdump.c) e um testador de histórico (histtest.ec - ele afirma ser ESQL / C, mas é realmente um código C; uma das funções de suporte que ele chama usa algum Informix ESQL / C funções da biblioteca). Entre em contato comigo se desejar experimentar sem usar o Informix ESQL / C - veja meu perfil. Existem algumas mudanças triviais para compilar o teste de história fora do ambiente de design, além de você precisar de um makefile.

Jonathan Leffler
fonte
0

Concordo com o comentário dos pehrs à sua pergunta. A rotação de logs não é tão difícil. Você pode configurar o logrotate ou outro script para verificar periodicamente seu arquivo de log, mesmo que a cada minuto, se desejar. Quando detecta que seu arquivo atinge 1 GB de tamanho, ele simplesmente renomeia, o que leva quase sem E / S. Durante a renomeação, o processo continua gravando o arquivo de log. O rotator de log pode enviar um HUP ao seu daemon syslog (seu daemon está efetuando logon no syslog, certo? Se não, ele deve suportar o sinal HUP se estiver bem escrito ...) para reabrir o caminho do arquivo original . Nesse ponto, ele começará a gravar em um novo arquivo no caminho original e você poderá excluir a versão girada.

Kamil Kisiel
fonte