Faça o log de um FIFO e redirecione para um arquivo?

8

Eu tenho um aplicativo que deve registrar cada transação. Cada mensagem de log é liberada porque precisamos ter um registro do que ocorreu antes de uma falha. Meus colegas e eu estávamos curiosos sobre como alcançar os efeitos de desempenho do buffer, garantindo que a mensagem de log tivesse deixado o processo.

O que nos surgiu foi:

  • cria um FIFO para o qual o aplicativo pode gravar e
  • redireciona o conteúdo desse FIFO para um arquivo normal via cat .

Ou seja, o que normalmente é:

app --logfile logfile.txt

é agora:

mkfifo logfifo
cat logfifo &> logfile.txt &
app --logfile logfifo

Existem algumas dicas para essa abordagem? Funcionou quando testamos, mas queremos ter absoluta certeza de que as mensagens encontrarão o caminho para o arquivo de redirecionamento, mesmo se o aplicativo original falhar.

(Não temos o código-fonte do aplicativo, portanto as soluções de programação estão fora de questão. Além disso, o aplicativo não grava em stdout , portanto, canalizar diretamente para um comando diferente está fora de questão. Então, syslog não é uma possibilidade.)

Atualização: adicionei uma recompensa. A resposta aceita será não envolvendo logger pela simples razão de que logger é não sobre o que eu perguntei. Como a pergunta original declara, estou apenas procurando pegadinhas usando um FIFO.

    
por chrisaycock 15.02.2012 / 21:23

6 respostas

5

Note que um fifo é normalmente necessário na programação, onde a quantidade escrita pode ultrapassar a quantidade lida.

Como tal, um fifo não funciona perfeitamente como você antecipa, mas resolveria seu problema principal enquanto introduzia outro.

Existem três possíveis advertências.

  1. Escrever no fifo é bloqueado indefinidamente se nada estiver lendo o outro lado na inicialização.
  2. O fifo tem uma largura fixa de 64K, pela qual, se o buffer for preenchido até esse ponto, gravações adicionais serão bloqueadas até que o leitor tenha captado.
  3. O gravador de cachimbos será morto com SIGPIPE se o leitor morrer ou sair.

Isso significará que seu problema (emulação de E / S armazenada em buffer em uma gravação sem buffer) será resolvido. Isso porque o novo 'limite' em sua FIFO se tornará, com efeito, a velocidade de qualquer utilitário que esteja gravando o que está no pipe para o disco (que presumivelmente será o buffer de E / S).

No entanto, o escritor se torna dependente do seu leitor de log para funcionar. Se o leitor parar de ler, o escritor irá bloquear. Se o leitor de repente sair (digamos que você fique sem espaço em disco no seu destino), o gravador irá SIGPIPE e provavelmente sairá.

Outro ponto a ser mencionado é que, se o servidor entrar em pane e o kernel parar de responder, você poderá perder até 64k de dados que estavam nesse buffer.

Outra maneira de corrigir isso é gravar logs em tmpfs (/ dev / shm no linux) e ajustar a saída para um local de disco fixo. Há limites menos restritivos na alocação de memória ao fazer isso (não 64K, normalmente 2G!), Mas pode não funcionar se o gravador não tiver uma maneira dinâmica de reabrir os arquivos de log (você teria que limpar periodicamente os logs do tmpfs). Se o servidor entrar em pane nesse método, você poderá perder muito mais dados.

    
por 23.02.2012 / 16:43
4
mkfifo logfifo
cat logfifo &> logfile.txt &
app --logfile logfifo

O que acontece quando o processo cat logfifo morre, alguém o mata por acidente ou alguém o aponta acidentalmente para o local errado?

Minha experiência é que o app irá bloquear e travar rapidamente. Eu tentei isso com o Tomcat, Apache e alguns aplicativos pequenos construídos em casa, e corri para o mesmo problema. Nunca investiguei muito, porque logger ou simples redirecionamento de E / S fez o que eu quero. Eu geralmente não preciso da integridade do registro, que é o que você está tentando seguir. E como você diz, você não quer logger.

Existe alguma discussão sobre este problema em fifo Linux non-blocking (em registro de demanda) .

    
por 22.02.2012 / 01:35
2

Suas opções são bastante limitadas pelo aplicativo, mas o que você testou funcionará.

Fazemos algo semelhante com o verniz e o varnishncsa para obter os logs em algum lugar útil para nós. Nós temos um fifo e apenas lemos dele com o syslog-ng e o enviamos onde precisamos. Nós lidamos com cerca de 50 GB e ainda não encontramos um problema com essa abordagem.

    
por 15.02.2012 / 22:24
2

O ambiente é o CentOS e o aplicativo grava em um arquivo ...

Em vez de enviar para um arquivo normal, eu enviaria a saída para o syslog e garantiria que as mensagens do syslog estivessem sendo enviadas para um servidor central e também localmente.

Você deve poder usar um script de shell como este:

logger -p daemon.notice -t app < fifo

Você também pode aceitar a entrada (para logger ) de cat ou de tail -f em um canal:

tail -f fifo | logger ...
cat fifo | logger ...

O único problema é que ele não se diferencia com base na importância da mensagem de log (tudo é AVISO ), mas pelo menos é registrado e também enviado para fora do host para um servidor central.

Configurar o syslog depende de qual servidor você está usando. Há rsyslog e syslog-ng (ambos muito capazes).

EDIT : revisado depois de obter mais informações do pôster.

    
por 15.02.2012 / 21:29
1

Você escreve:

Also, the application won't write to stdout...

Você tentou fazer login no "arquivo" /dev/stdout ? Isso pode permitir que você faça algo como:

app --logfile /dev/stdout | logger -t app
    
por 20.02.2012 / 17:43
1

Não há sentido em escrever para um fifo e depois ter outro processo para gravá-lo em um arquivo. Basta escrever diretamente no arquivo normalmente e assim que o write() retornar, ele estará nas mãos do kernel; ele ainda gravará no disco se o aplicativo falhar.

    
por 22.02.2012 / 00:06

Tags